Compare commits
152 Commits
curl-7_31_
...
curl-7_32_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
70812c2f32 | ||
![]() |
a64bca68c7 | ||
![]() |
67633e1308 | ||
![]() |
715ca7c5fe | ||
![]() |
001758760b | ||
![]() |
2f06265e39 | ||
![]() |
432431368f | ||
![]() |
4b0028f82d | ||
![]() |
8c9236bb2c | ||
![]() |
2af0b10c95 | ||
![]() |
08adecc9a1 | ||
![]() |
015556d74c | ||
![]() |
4c40fe64b8 | ||
![]() |
d20def2046 | ||
![]() |
d2b36e466a | ||
![]() |
27f8c93daf | ||
![]() |
058b86e6f3 | ||
![]() |
0018d6830e | ||
![]() |
59224a31fd | ||
![]() |
0994d737c8 | ||
![]() |
96749554fd | ||
![]() |
785749405f | ||
![]() |
7cc00d9a83 | ||
![]() |
230e16dc03 | ||
![]() |
0ce410a629 | ||
![]() |
5d3cbde72e | ||
![]() |
8fe8fd2b17 | ||
![]() |
0ddc678927 | ||
![]() |
51f0b798fa | ||
![]() |
6b27703b5f | ||
![]() |
045ccb59a4 | ||
![]() |
784336deec | ||
![]() |
eb41e8eebe | ||
![]() |
3cd43bbfec | ||
![]() |
204e340bcd | ||
![]() |
37f2ba7e57 | ||
![]() |
09b9fc9009 | ||
![]() |
7da3caaf95 | ||
![]() |
82ab5f1b0c | ||
![]() |
7ae64af368 | ||
![]() |
2ad688ed7c | ||
![]() |
ca786233d2 | ||
![]() |
14a3139c4d | ||
![]() |
5af2bfb955 | ||
![]() |
1691a31cab | ||
![]() |
9dedcbf9ec | ||
![]() |
537ffc4c69 | ||
![]() |
c3e7210548 | ||
![]() |
9a5c2d8373 | ||
![]() |
8693bbd8c4 | ||
![]() |
251dd03b88 | ||
![]() |
55ea83d622 | ||
![]() |
b5478a0e03 | ||
![]() |
db2deba6b4 | ||
![]() |
41fb6443ce | ||
![]() |
e5dfe6c282 | ||
![]() |
e277e20a6d | ||
![]() |
a23e56d109 | ||
![]() |
ca89a0a092 | ||
![]() |
50a74be125 | ||
![]() |
8c1e3bb713 | ||
![]() |
4fad1943a2 | ||
![]() |
4d346673a2 | ||
![]() |
de052ca6fc | ||
![]() |
1a593191c2 | ||
![]() |
2c4ef997b9 | ||
![]() |
d020e2c381 | ||
![]() |
48fe9226a0 | ||
![]() |
a77ac42e52 | ||
![]() |
5880db8abd | ||
![]() |
0f4ba89ffd | ||
![]() |
edeb1ae65f | ||
![]() |
82232bbbaf | ||
![]() |
bb2e0686ab | ||
![]() |
513e587c5e | ||
![]() |
6ed2bcc5f5 | ||
![]() |
d529f3882b | ||
![]() |
e2e92486a7 | ||
![]() |
2e5b3168d6 | ||
![]() |
6bcacff1a5 | ||
![]() |
12d01cb6fa | ||
![]() |
90695fb2c5 | ||
![]() |
dd17069c9e | ||
![]() |
26b0cb6ae2 | ||
![]() |
6d30f8ebed | ||
![]() |
11220678c4 | ||
![]() |
448d55ef0a | ||
![]() |
7b115cc1e1 | ||
![]() |
a10d5e3851 | ||
![]() |
1016637f5a | ||
![]() |
2e00872c04 | ||
![]() |
56ece42c81 | ||
![]() |
99924f6606 | ||
![]() |
0eba02fd41 | ||
![]() |
464c8693d2 | ||
![]() |
50af17ef24 | ||
![]() |
3a24cb7bc4 | ||
![]() |
e839446c2a | ||
![]() |
695931cf8e | ||
![]() |
964a7600b9 | ||
![]() |
d4492f955d | ||
![]() |
9c15325d34 | ||
![]() |
d8c04909fa | ||
![]() |
c0a7a98aee | ||
![]() |
f5005dd8d0 | ||
![]() |
d3aaa68f55 | ||
![]() |
cfc907e43d | ||
![]() |
2af64c6432 | ||
![]() |
83f0dae129 | ||
![]() |
65d53cf6ef | ||
![]() |
0d9e65f79f | ||
![]() |
c983aa9efc | ||
![]() |
b16b7f9d3a | ||
![]() |
5c6f12b9f2 | ||
![]() |
2022b10e50 | ||
![]() |
45339625bc | ||
![]() |
20ff820ef2 | ||
![]() |
39e85d99fe | ||
![]() |
3a0e931fc7 | ||
![]() |
fe7e3229f8 | ||
![]() |
ecf042ff3c | ||
![]() |
aff245b360 | ||
![]() |
e01469907a | ||
![]() |
b7a933154a | ||
![]() |
54f18e5427 | ||
![]() |
833fba265d | ||
![]() |
d633052905 | ||
![]() |
009d2336fe | ||
![]() |
abca89aaa0 | ||
![]() |
d689376cb0 | ||
![]() |
98b0d66eb4 | ||
![]() |
9c2853f2ae | ||
![]() |
aff7562922 | ||
![]() |
365c5ba395 | ||
![]() |
cb1aa8b0e3 | ||
![]() |
d3d5c4a40e | ||
![]() |
6117d4025e | ||
![]() |
d23745f7c9 | ||
![]() |
ad47d8e263 | ||
![]() |
8a7a277c08 | ||
![]() |
0030fbd382 | ||
![]() |
f3052c8a81 | ||
![]() |
7d80ed64e4 | ||
![]() |
a2e0ce86ba | ||
![]() |
6fab0bd9f1 | ||
![]() |
02964ed630 | ||
![]() |
6f3e7aabdc | ||
![]() |
631e3e13a9 | ||
![]() |
832c195179 | ||
![]() |
7877619f85 | ||
![]() |
ec248b590d | ||
![]() |
4846b5e9fe |
@@ -148,12 +148,24 @@ vc-ssl-zlib: $(VC)
|
||||
cd ..\src
|
||||
nmake /f Makefile.$(VC) cfg=release-ssl-zlib
|
||||
|
||||
vc-winssl-zlib: $(VC)
|
||||
cd lib
|
||||
nmake /f Makefile.$(VC) cfg=release-winssl-zlib
|
||||
cd ..\src
|
||||
nmake /f Makefile.$(VC) cfg=release-winssl-zlib
|
||||
|
||||
vc-x64-ssl-zlib: $(VC)
|
||||
cd lib
|
||||
nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib
|
||||
cd ..\src
|
||||
nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-ssl-zlib
|
||||
|
||||
vc-x64-winssl-zlib: $(VC)
|
||||
cd lib
|
||||
nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-winssl-zlib
|
||||
cd ..\src
|
||||
nmake /f Makefile.$(VC) MACHINE=x64 cfg=release-winssl-zlib
|
||||
|
||||
vc-ssl-dll: $(VC)
|
||||
cd lib
|
||||
nmake /f Makefile.$(VC) cfg=release-ssl-dll
|
||||
|
163
RELEASE-NOTES
163
RELEASE-NOTES
@@ -1,11 +1,11 @@
|
||||
Curl and libcurl 7.31.0
|
||||
Curl and libcurl 7.32.0
|
||||
|
||||
Public curl releases: 133
|
||||
Public curl releases: 134
|
||||
Command line options: 152
|
||||
curl_easy_setopt() options: 199
|
||||
Public functions in libcurl: 58
|
||||
Known libcurl bindings: 42
|
||||
Contributors: 1005
|
||||
Contributors: 1049
|
||||
|
||||
***
|
||||
krb4 support is up for removal. If you care about it at all, speak up
|
||||
@@ -14,58 +14,56 @@ Curl and libcurl 7.31.0
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o darwinssl: add TLS session resumption
|
||||
o darwinssl: add TLS crypto authentication
|
||||
o imap/pop3/smtp: Added support for ;auth=<mech> in the URL
|
||||
o imap/pop3/smtp: Added support for ;auth=<mech> to CURLOPT_USERPWD
|
||||
o usercertinmem.c: add example showing user cert in memory
|
||||
o url: Added smtp and pop3 hostnames to the protocol detection list
|
||||
o imap/pop3/smtp: Added support for enabling the SASL initial response [8]
|
||||
o curl -E: allow to use ':' in certificate nicknames [10]
|
||||
o curl: allow timeouts to accept decimal values
|
||||
o OS400: add slist and certinfo EBCDIC support
|
||||
o OS400: new SSL backend GSKit
|
||||
o CURLOPT_XFERINFOFUNCTION: introducing a new progress callback
|
||||
o LIBCURL-STRUCTS: new document
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o SECURITY VULNERABILITY: curl_easy_unescape() may parse data beyond the end
|
||||
of the input buffer [26]
|
||||
|
||||
o FTP: access files in root dir correctly [1]
|
||||
o configure: try pthread_create without -lpthread [2]
|
||||
o FTP: handle a 230 welcome response [3]
|
||||
o curl-config: don't output static libs when they are disabled
|
||||
o CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling [4]
|
||||
o Various documentation updates
|
||||
o getinfo.c: reset timecond when clearing session-info variables [5]
|
||||
o FILE: prevent an artificial timeout event due to stale speed-check data [6]
|
||||
o ftp_state_pasv_resp: connect through proxy also when set by env [7]
|
||||
o sshserver: disable StrictHostKeyChecking
|
||||
o ftpserver: Fixed imap logout confirmation data
|
||||
o curl_easy_init: use less mallocs
|
||||
o smtp: Fixed unknown percentage complete in progress bar
|
||||
o smtp: Fixed sending of double CRLF caused by first in EOB
|
||||
o bindlocal: move brace out of #ifdef [9]
|
||||
o winssl: Fixed invalid memory access during SSL shutdown [11]
|
||||
o OS X framework: fix invalid symbolic link
|
||||
o OpenSSL: allow empty server certificate subject [12]
|
||||
o axtls: prevent memleaks on SSL handshake failures
|
||||
o cookies: only consider full path matches
|
||||
o Revert win32 MemoryTracking: wcsdup() _wcsdup() and _tcsdup() [13]
|
||||
o Curl_cookie_add: handle IPv6 hosts [14]
|
||||
o ossl_send: SSL_write() returning 0 is an error too
|
||||
o ossl_recv: SSL_read() returning 0 is an error too
|
||||
o Digest auth: escape user names with \ or " in them [15]
|
||||
o curl_formadd.3: fixed wrong "end-marker" syntax [16]
|
||||
o libcurl-tutorial.3: fix incorrect backslash [17]
|
||||
o curl_multi_wait: reduce timeout if the multi handle wants to [18]
|
||||
o tests/Makefile: typo in the perlcheck target [19]
|
||||
o axtls: honor disabled VERIFYHOST
|
||||
o OpenSSL: avoid double free in the PKCS12 certificate code [20]
|
||||
o multi_socket: reduce timeout inaccuracy margin [21]
|
||||
o digest: support auth-int for empty entity body [22]
|
||||
o axtls: now done non-blocking
|
||||
o lib1900: use tutil_tvnow instead of gettimeofday
|
||||
o curl_easy_perform: avoid busy-looping [23]
|
||||
o CURLOPT_COOKIELIST: take cookie share lock [24]
|
||||
o multi_socket: react on socket close immediately [25]
|
||||
o dotdot: introducing dot file path cleanup [1]
|
||||
o docs: fix typo in curl_easy_getinfo manpage
|
||||
o test1230: avoid using hard-wired port number
|
||||
o test1396: invoke the correct test tool
|
||||
o SIGPIPE: ignored while inside the library [2]
|
||||
o darwinssl: fix crash that started happening in Lion
|
||||
o OpenSSL: check for read errors, don't assume [3]
|
||||
o c-ares: improve error message on failed resolve [4]
|
||||
o printf: make sure %x are treated unsigned
|
||||
o formpost: better random boundaries [5]
|
||||
o url: restore the functionality of 'curl -u :' [6]
|
||||
o curl.1: fix typo in --xattr description [7]
|
||||
o digest: improve nonce generation
|
||||
o configure: automake 1.14 compatibility tweak
|
||||
o curl.1: document the --post303 option in the man page
|
||||
o curl.1: document the --sasl-ir option in the man page
|
||||
o setup-vms.h: sk_pop symbol tweak
|
||||
o tool_paramhlp: try harder to catch negatives
|
||||
o cmake: Fix for MSVC2010 project generation [8]
|
||||
o asyn-ares: Don't blank ares servers if none configured
|
||||
o curl_multi_wait: set revents for extra fds
|
||||
o Reinstate "WIN32 MemoryTracking: track wcsdup() _wcsdup() and _tcsdup()
|
||||
o ftp_do_more: consider DO_MORE complete when server connects back [9]
|
||||
o curl_easy_perform: gradually increase the delay time [10]
|
||||
o curl: fix symbolic names for CURLUSESSL_* enum in --libcurl output
|
||||
o curl: fix upload of a zip file in OpenVMS [11]
|
||||
o build: fix linking on Solaris 10 [12]
|
||||
o curl_formadd: CURLFORM_FILECONTENT wrongly rejected some option combos [13]
|
||||
o curl_formadd: fix file upload on VMS [14]
|
||||
o curl_easy_pause: on unpause, trigger mulit-socket handling [15]
|
||||
o md5 & metalink: use better build macros on Apple operating systems [16]
|
||||
o darwinssl: fix build error in crypto authentication under Snow Leopard [16]
|
||||
o curl: make --progress-bar update the line less frequently [17]
|
||||
o configure: don't error out on variable confusions (CFLAGS, LDFLAGS etc)
|
||||
o mk-ca-bundle: skip more untrusted certificates
|
||||
o formadd: wrong pointer for file name when CURLFORM_BUFFERPTR used [18]
|
||||
o FTP: when EPSV gets a 229 but fails to connect, retry with PASV
|
||||
o mk-ca-bundle.1: don't install on make install [19]
|
||||
o VMS: lots of updates and fixes of the build procedure
|
||||
o global dns cache: didn't work (regression)
|
||||
o global dns cache: fix memory leak
|
||||
o
|
||||
|
||||
This release includes the following known bugs:
|
||||
|
||||
@@ -74,43 +72,34 @@ 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:
|
||||
|
||||
David Strauss, Kamil Dudka, Steve Holme, Nick Zitzmann, Sam Deane, Duncan,
|
||||
Anders Havn, Dan Fandrich, Paul Howarth, Dave Reisner, Wouter Van Rooy,
|
||||
Linus Nielsen Feltzing, Ishan SinghLevett, Alessandro Ghedini,
|
||||
Ludovico Cavedon, Zdenek Pavlas, Zekun Ni, Lars Johannesen, Marc Hoersken,
|
||||
Renaud Guillard, John Gardiner Myers, Jared Jennings, Eric Hu,
|
||||
Yamada Yasuharu, Stefan Neis, Mike Giancola, Eric S. Raymond, Andrii Moiseiev,
|
||||
Christian Weisgerber, Peter Gal, Aleksey Tulinov, Hang Su, Sergei Nikulov,
|
||||
Miguel Angel, Nach M. S., Benjamin Gilbert, Erik Johansson, Timo Sirainen,
|
||||
Guenter Knauf
|
||||
Alex Vinnik, Alessandro Ghedini, Nick Zitzmann, Kamil Dudka,
|
||||
Lluis Batlle i Rossell, Nach M. S., Kim Vandry, Ben Greear, Dan Fandrich,
|
||||
Dave Reisner, Evgeny Turnaev, Guenter Knauf, John E. Malmberg, Marc Hoersken,
|
||||
Patrick Monnerat, Sergei Nikulov, Yang Tse, Andreas Malzahn, Clemens Gruber,
|
||||
Jean-Noel Rouvignac, Markus Moeller, Fabian Keil, Dagobert Michelsen,
|
||||
Byrial Jensen, Justin Karneges, Edward Rudd, Marc Doughty, Konstantin Isakov,
|
||||
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
[1] = http://curl.haxx.se/mail/lib-2013-04/0142.html
|
||||
[2] = http://curl.haxx.se/bug/view.cgi?id=1216
|
||||
[3] = http://curl.haxx.se/mail/lib-2013-02/0102.html
|
||||
[4] = http://curl.haxx.se/mail/lib-2013-04/0294.html
|
||||
[5] = http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783
|
||||
[6] = https://bugzilla.redhat.com/906031
|
||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1218
|
||||
[8] = http://curl.haxx.se/mail/lib-2012-03/0114.html
|
||||
[9] = http://curl.haxx.se/mail/lib-2013-05/0000.html
|
||||
[10] = http://curl.haxx.se/bug/view.cgi?id=1196
|
||||
[11] = http://curl.haxx.se/bug/view.cgi?id=1219
|
||||
[12] = http://curl.haxx.se/bug/view.cgi?id=1220
|
||||
[13] = http://curl.haxx.se/mail/lib-2013-05/0070.html
|
||||
[14] = http://curl.haxx.se/bug/view.cgi?id=1221
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1230
|
||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1233
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1234
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1224
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1239
|
||||
[20] = http://curl.haxx.se/bug/view.cgi?id=1236
|
||||
[21] = http://curl.haxx.se/bug/view.cgi?id=1228
|
||||
[22] = http://curl.haxx.se/bug/view.cgi?id=1235
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1238
|
||||
[24] = http://curl.haxx.se/bug/view.cgi?id=1215
|
||||
[25] = http://curl.haxx.se/bug/view.cgi?id=1248
|
||||
[26] = http://curl.haxx.se/docs/adv_20130622.html
|
||||
[1] = http://curl.haxx.se/bug/view.cgi?id=1200
|
||||
[2] = http://curl.haxx.se/bug/view.cgi?id=1180
|
||||
[3] = http://curl.haxx.se/bug/view.cgi?id=1249
|
||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1191
|
||||
[5] = http://curl.haxx.se/bug/view.cgi?id=1251
|
||||
[6] = http://curl.haxx.se/mail/archive-2013-06/0052.html
|
||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1252
|
||||
[8] = http://curl.haxx.se/mail/lib-2013-07/0046.html
|
||||
[9] = http://curl.haxx.se/mail/lib-2013-07/0115.html
|
||||
[10] = http://curl.haxx.se/mail/lib-2013-07/0103.html
|
||||
[11] = http://curl.haxx.se/bug/view.cgi?id=496
|
||||
[12] = http://curl.haxx.se/bug/view.cgi?id=1217
|
||||
[13] = http://curl.haxx.se/mail/lib-2013-07/0258.html
|
||||
[14] = http://curl.haxx.se/bug/view.cgi?id=758
|
||||
[15] = http://curl.haxx.se/mail/lib-2013-07/0239.html
|
||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1255
|
||||
[17] = http://curl.haxx.se/mail/archive-2013-07/0031.html
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1262
|
||||
[19] = http://curl.haxx.se/mail/lib-2013-08/0057.html
|
||||
|
@@ -126,7 +126,7 @@ fi
|
||||
dnl figure out the libcurl version
|
||||
CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h`
|
||||
XC_CHECK_PROG_CC
|
||||
AM_INIT_AUTOMAKE
|
||||
XC_AUTOMAKE
|
||||
AC_MSG_CHECKING([curl version])
|
||||
AC_MSG_RESULT($CURLVERSION)
|
||||
|
||||
@@ -3531,6 +3531,8 @@ AC_OUTPUT
|
||||
|
||||
CURL_GENERATE_CONFIGUREHELP_PM
|
||||
|
||||
XC_AMEND_DISTCLEAN([lib src tests/unit tests/server tests/libtest docs/examples])
|
||||
|
||||
AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
|
||||
curl version: ${CURLVERSION}
|
||||
|
@@ -79,9 +79,9 @@
|
||||
1.3 What To Read
|
||||
|
||||
Source code, the man pages, the INTERNALS document, TODO, KNOWN_BUGS, the
|
||||
most recent CHANGES. Just lurking on the libcurl mailing list is gonna give
|
||||
you a lot of insights on what's going on right now. Asking there is a good
|
||||
idea too.
|
||||
most recent CHANGES. Just lurking on the curl-library mailing list is gonna
|
||||
give you a lot of insights on what's going on right now. Asking there is a
|
||||
good idea too.
|
||||
|
||||
2. cURL Coding Standards
|
||||
|
||||
@@ -98,12 +98,12 @@
|
||||
|
||||
2.2 Indenting
|
||||
|
||||
Please try using the same indenting levels and bracing method as all the
|
||||
other code already does. It makes the source code a lot easier to follow if
|
||||
all of it is written using the same style. We don't ask you to like it, we
|
||||
just ask you to follow the tradition! ;-) This mainly means: 2-level indents,
|
||||
using spaces only (no tabs) and having the opening brace ({) on the same line
|
||||
as the if() or while().
|
||||
Use the same indenting levels and bracing method as all the other code
|
||||
already does. It makes the source code easier to follow if all of it is
|
||||
written using the same style. We don't ask you to like it, we just ask you to
|
||||
follow the tradition! ;-) This mainly means: 2-level indents, using spaces
|
||||
only (no tabs) and having the opening brace ({) on the same line as the if()
|
||||
or while().
|
||||
|
||||
Also note that we use if() and while() with no space before the parenthesis.
|
||||
|
||||
@@ -151,6 +151,9 @@
|
||||
description exactly what they correct so that all patches can be selectively
|
||||
applied by the maintainer or other interested parties.
|
||||
|
||||
Also, separate patches enable bisecting much better when we track problems in
|
||||
the future.
|
||||
|
||||
2.9 Patch Against Recent Sources
|
||||
|
||||
Please try to get the latest available sources to make your patches
|
||||
@@ -178,6 +181,10 @@
|
||||
test case that verifies that it works as documented. If every submitter also
|
||||
posts a few test cases, it won't end up as a heavy burden on a single person!
|
||||
|
||||
If you don't have test cases or perhaps you have done something that is very
|
||||
hard to write tests for, do explain exactly how you have otherwise tested and
|
||||
verified your changes.
|
||||
|
||||
3. Pushing Out Your Changes
|
||||
|
||||
3.1 Write Access to git Repository
|
||||
|
@@ -1045,7 +1045,7 @@ PORTS
|
||||
- Alpha OpenVMS V7.1-1H2
|
||||
- Alpha Tru64 v5.0 5.1
|
||||
- AVR32 Linux
|
||||
- ARM Android 1.5, 2.1
|
||||
- ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
|
||||
- ARM INTEGRITY
|
||||
- ARM iOS
|
||||
- Cell Linux
|
||||
@@ -1116,6 +1116,7 @@ GNU GSS http://www.gnu.org/software/gss/
|
||||
GnuTLS http://www.gnu.org/software/gnutls/
|
||||
Heimdal http://www.pdc.kth.se/heimdal/
|
||||
libidn http://www.gnu.org/software/libidn/
|
||||
libmetalink https://launchpad.net/libmetalink/
|
||||
libssh2 http://www.libssh2.org/
|
||||
MIT Kerberos http://web.mit.edu/kerberos/www/dist/
|
||||
NSS http://www.mozilla.org/projects/security/pki/nss/
|
||||
|
113
docs/INTERNALS
113
docs/INTERNALS
@@ -111,6 +111,9 @@ Windows vs Unix
|
||||
Library
|
||||
=======
|
||||
|
||||
(See LIBCURL-STRUCTS for a separate document describing all major internal
|
||||
structs and their purposes.)
|
||||
|
||||
There are plenty of entry points to the library, namely each publicly defined
|
||||
function that libcurl offers to applications. All of those functions are
|
||||
rather small and easy-to-follow. All the ones prefixed with 'curl_easy' are
|
||||
@@ -135,16 +138,18 @@ Library
|
||||
options is documented in the man page. This function mainly sets things in
|
||||
the 'SessionHandle' struct.
|
||||
|
||||
curl_easy_perform() does a whole lot of things:
|
||||
curl_easy_perform() is just a wrapper function that makes use of the multi
|
||||
API. It basically curl_multi_init(), curl_multi_add_handle(),
|
||||
curl_multi_wait(), and curl_multi_perform() until the transfer is done and
|
||||
then returns.
|
||||
|
||||
It starts off in the lib/easy.c file by calling Curl_perform() and the main
|
||||
work then continues in lib/url.c. The flow continues with a call to
|
||||
Curl_connect() to connect to the remote site.
|
||||
Some of the most important key functions in url.c are called from multi.c
|
||||
when certain key steps are to be made in the transfer operation.
|
||||
|
||||
o Curl_connect()
|
||||
|
||||
... analyzes the URL, it separates the different components and connects to
|
||||
the remote host. This may involve using a proxy and/or using SSL. The
|
||||
Analyzes the URL, it separates the different components and connects to the
|
||||
remote host. This may involve using a proxy and/or using SSL. The
|
||||
Curl_resolv() function in lib/hostip.c is used for looking up host names
|
||||
(it does then use the proper underlying method, which may vary between
|
||||
platforms and builds).
|
||||
@@ -160,10 +165,7 @@ Library
|
||||
o Curl_do()
|
||||
|
||||
Curl_do() makes sure the proper protocol-specific function is called. The
|
||||
functions are named after the protocols they handle. Curl_ftp(),
|
||||
Curl_http(), Curl_dict(), etc. They all reside in their respective files
|
||||
(ftp.c, http.c and dict.c). HTTPS is handled by Curl_http() and FTPS by
|
||||
Curl_ftp().
|
||||
functions are named after the protocols they handle.
|
||||
|
||||
The protocol-specific functions of course deal with protocol-specific
|
||||
negotiations and setup. They have access to the Curl_sendf() (from
|
||||
@@ -182,10 +184,9 @@ Library
|
||||
be called with some basic info about the upcoming transfer: what socket(s)
|
||||
to read/write and the expected file transfer sizes (if known).
|
||||
|
||||
o Transfer()
|
||||
o Curl_readwrite()
|
||||
|
||||
Curl_perform() then calls Transfer() in lib/transfer.c that performs the
|
||||
entire file transfer.
|
||||
Called during the transfer of the actual protocol payload.
|
||||
|
||||
During transfer, the progress functions in lib/progress.c are called at a
|
||||
frequent interval (or at the user's choice, a specified callback might get
|
||||
@@ -207,33 +208,11 @@ Library
|
||||
used. This function is only used when we are certain that no more transfers
|
||||
is going to be made on the connection. It can be also closed by force, or
|
||||
it can be called to make sure that libcurl doesn't keep too many
|
||||
connections alive at the same time (there's a default amount of 5 but that
|
||||
can be changed with the CURLOPT_MAXCONNECTS option).
|
||||
connections alive at the same time.
|
||||
|
||||
This function cleans up all resources that are associated with a single
|
||||
connection.
|
||||
|
||||
Curl_perform() is the function that does the main "connect - do - transfer -
|
||||
done" loop. It loops if there's a Location: to follow.
|
||||
|
||||
When completed, the curl_easy_cleanup() should be called to free up used
|
||||
resources. It runs Curl_disconnect() on all open connections.
|
||||
|
||||
A quick roundup on internal function sequences (many of these call
|
||||
protocol-specific function-pointers):
|
||||
|
||||
Curl_connect - connects to a remote site and does initial connect fluff
|
||||
This also checks for an existing connection to the requested site and uses
|
||||
that one if it is possible.
|
||||
|
||||
Curl_do - starts a transfer
|
||||
Curl_handler::do_it() - transfers data
|
||||
Curl_done - ends a transfer
|
||||
|
||||
Curl_disconnect - disconnects from a remote site. This is called when the
|
||||
disconnect is really requested, which doesn't necessarily have to be
|
||||
exactly after curl_done in case we want to keep the connection open for
|
||||
a while.
|
||||
|
||||
HTTP(S)
|
||||
|
||||
@@ -316,48 +295,38 @@ Persistent Connections
|
||||
hold connection-oriented data. It is meant to hold the root data as well as
|
||||
all the options etc that the library-user may choose.
|
||||
o The 'SessionHandle' struct holds the "connection cache" (an array of
|
||||
pointers to 'connectdata' structs). There's one connectdata struct
|
||||
allocated for each connection that libcurl knows about. Note that when you
|
||||
use the multi interface, the multi handle will hold the connection cache
|
||||
and not the particular easy handle. This of course to allow all easy handles
|
||||
in a multi stack to be able to share and re-use connections.
|
||||
pointers to 'connectdata' structs).
|
||||
o This enables the 'curl handle' to be reused on subsequent transfers.
|
||||
o When we are about to perform a transfer with curl_easy_perform(), we first
|
||||
check for an already existing connection in the cache that we can use,
|
||||
otherwise we create a new one and add to the cache. If the cache is full
|
||||
already when we add a new connection, we close one of the present ones. We
|
||||
select which one to close dependent on the close policy that may have been
|
||||
previously set.
|
||||
o When the transfer operation is complete, we try to leave the connection
|
||||
open. Particular options may tell us not to, and protocols may signal
|
||||
closure on connections and then we don't keep it open of course.
|
||||
o When libcurl is told to perform a transfer, it first checks for an already
|
||||
existing connection in the cache that we can use. Otherwise it creates a
|
||||
new one and adds that the cache. If the cache is full already when a new
|
||||
conncetion is added added, it will first close the oldest unused one.
|
||||
o When the transfer operation is complete, the connection is left
|
||||
open. Particular options may tell libcurl not to, and protocols may signal
|
||||
closure on connections and then they won't be kept open of course.
|
||||
o When curl_easy_cleanup() is called, we close all still opened connections,
|
||||
unless of course the multi interface "owns" the connections.
|
||||
|
||||
You do realize that the curl handle must be re-used in order for the
|
||||
persistent connections to work.
|
||||
The curl handle must be re-used in order for the persistent connections to
|
||||
work.
|
||||
|
||||
multi interface/non-blocking
|
||||
============================
|
||||
|
||||
We make an effort to provide a non-blocking interface to the library, the
|
||||
multi interface. To make that interface work as good as possible, no
|
||||
low-level functions within libcurl must be written to work in a blocking
|
||||
manner.
|
||||
The multi interface is a non-blocking interface to the library. To make that
|
||||
interface work as good as possible, no low-level functions within libcurl
|
||||
must be written to work in a blocking manner. (There are still a few spots
|
||||
violating this rule.)
|
||||
|
||||
One of the primary reasons we introduced c-ares support was to allow the name
|
||||
resolve phase to be perfectly non-blocking as well.
|
||||
|
||||
The ultimate goal is to provide the easy interface simply by wrapping the
|
||||
multi interface functions and thus treat everything internally as the multi
|
||||
interface is the single interface we have.
|
||||
|
||||
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. They are built around state machines that return when they could
|
||||
block waiting for data. The DICT, LDAP and TELNET protocols are crappy
|
||||
examples and they are subject for rewrite in the future to better fit the
|
||||
libcurl protocol family.
|
||||
The FTP and the SFTP/SCP protocols are examples of how we adapt and adjust
|
||||
the code to allow non-blocking operations even on multi-stage command-
|
||||
response protocols. They are built around state machines that return when
|
||||
they would otherwise block waiting for data. The DICT, LDAP and TELNET
|
||||
protocols are crappy examples and they are subject for rewrite in the future
|
||||
to better fit the libcurl protocol family.
|
||||
|
||||
SSL libraries
|
||||
=============
|
||||
@@ -408,12 +377,12 @@ API/ABI
|
||||
Client
|
||||
======
|
||||
|
||||
main() resides in src/main.c together with most of the client code.
|
||||
main() resides in src/tool_main.c.
|
||||
|
||||
src/tool_hugehelp.c is automatically generated by the mkhelp.pl perl script
|
||||
to display the complete "manual" and the src/urlglob.c file holds the
|
||||
functions used for the URL-"globbing" support. Globbing in the sense that
|
||||
the {} and [] expansion stuff is there.
|
||||
to display the complete "manual" and the src/tool_urlglob.c file holds the
|
||||
functions used for the URL-"globbing" support. Globbing in the sense that the
|
||||
{} and [] expansion stuff is there.
|
||||
|
||||
The client mostly messes around to setup its 'config' struct properly, then
|
||||
it calls the curl_easy_*() functions of the library and when it gets back
|
||||
@@ -425,8 +394,8 @@ Client
|
||||
curl_easy_getinfo() function to extract useful information from the curl
|
||||
session.
|
||||
|
||||
Recent versions may loop and do all this several times if many URLs were
|
||||
specified on the command line or config file.
|
||||
It may loop and do all this several times if many URLs were specified on the
|
||||
command line or config file.
|
||||
|
||||
Memory Debugging
|
||||
================
|
||||
|
@@ -3,6 +3,14 @@ join in and help us correct one or more of these! Also be sure to check the
|
||||
changelog of the current development status, as one or more of these problems
|
||||
may have been fixed since this was written!
|
||||
|
||||
83. curl is unable to load non-default openssl engines, because openssl isn't
|
||||
initialized properly. This seems to require OpenSSL_config() or
|
||||
CONF_modules_load_file() to be used by libcurl but the first seems to not
|
||||
work and we've gotten not reports from tests with the latter. Possibly we
|
||||
need to discuss with OpenSSL developers how this is supposed to be done. We
|
||||
need users with actual external openssl engines for testing to work on this.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1208
|
||||
|
||||
82. When building with the Windows Borland compiler, it fails because the
|
||||
"tlib" tool doesn't support hyphens (minus signs) in file names and we have
|
||||
such in the build.
|
||||
@@ -96,13 +104,6 @@ may have been fixed since this was written!
|
||||
CURLOPT_FAILONERROR with FTP to detect if a file exists or not, but it is
|
||||
not working: http://curl.haxx.se/mail/lib-2008-07/0295.html
|
||||
|
||||
57. On VMS-Alpha: When using an http-file-upload the file is not sent to the
|
||||
Server with the correct content-length. Sending a file with 511 or less
|
||||
bytes, content-length 512 is used. Sending a file with 513 - 1023 bytes,
|
||||
content-length 1024 is used. Files with a length of a multiple of 512 Bytes
|
||||
show the correct content-length. Only these files work for upload.
|
||||
http://curl.haxx.se/bug/view.cgi?id=2057858
|
||||
|
||||
56. When libcurl sends CURLOPT_POSTQUOTE commands when connected to a SFTP
|
||||
server using the multi interface, the commands are not being sent correctly
|
||||
and instead the connection is "cancelled" (the operation is considered done)
|
||||
@@ -180,12 +181,6 @@ may have been fixed since this was written!
|
||||
We probably have even more bugs and lack of features when a SOCKS proxy is
|
||||
used.
|
||||
|
||||
22. Sending files to a FTP server using curl on VMS, might lead to curl
|
||||
complaining on "unaligned file size" on completion. The problem is related
|
||||
to VMS file structures and the perceived file sizes stat() returns. A
|
||||
possible fix would involve sending a "STRU VMS" command.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1156287
|
||||
|
||||
21. FTP ASCII transfers do not follow RFC959. They don't convert the data
|
||||
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
|
||||
clearly describes how this should be done:
|
||||
|
245
docs/LIBCURL-STRUCTS
Normal file
245
docs/LIBCURL-STRUCTS
Normal file
@@ -0,0 +1,245 @@
|
||||
_ _ ____ _
|
||||
___| | | | _ \| |
|
||||
/ __| | | | |_) | |
|
||||
| (__| |_| | _ <| |___
|
||||
\___|\___/|_| \_\_____|
|
||||
|
||||
Structs in libcurl
|
||||
|
||||
This document should cover 7.32.0 pretty accurately, but will make sense even
|
||||
for older and later versions as things don't change drastically that often.
|
||||
|
||||
1. The main structs in libcurl
|
||||
1.1 SessionHandle
|
||||
1.2 connectdata
|
||||
1.3 Curl_multi
|
||||
1.4 Curl_handler
|
||||
1.5 conncache
|
||||
1.6 Curl_share
|
||||
1.7 CookieInfo
|
||||
|
||||
==============================================================================
|
||||
|
||||
1. The main structs in libcurl
|
||||
|
||||
1.1 SessionHandle
|
||||
|
||||
The SessionHandle handle struct is the one returned to the outside in the
|
||||
external API as a "CURL *". This is usually known as an easy handle in API
|
||||
documentations and examples.
|
||||
|
||||
Information and state that is related to the actual connection is in the
|
||||
'connectdata' struct. When a transfer is about to be made, libcurl will
|
||||
either create a new connection or re-use an existing one. The particular
|
||||
connectdata that is used by this handle is pointed out by
|
||||
SessionHandle->easy_conn.
|
||||
|
||||
Data and information that regard this particular single transfer is put in
|
||||
the SingleRequest sub-struct.
|
||||
|
||||
When the SessionHandle struct is added to a multi handle, as it must be in
|
||||
order to do any transfer, the ->multi member will point to the Curl_multi
|
||||
struct it belongs to. The ->prev and ->next members will then be used by the
|
||||
multi code to keep a linked list of SessionHandle structs that are added to
|
||||
that same multi handle. libcurl always uses multi so ->multi *will* point to
|
||||
a Curl_multi when a transfer is in progress.
|
||||
|
||||
->mstate is the multi state of this particular SessionHandle. When
|
||||
multi_runsingle() is called, it will act on this handle according to which
|
||||
state it is in. The mstate is also what tells which sockets to return for a
|
||||
speicific SessionHandle when curl_multi_fdset() is called etc.
|
||||
|
||||
The libcurl source code generally use the name 'data' for the variable that
|
||||
points to the SessionHandle.
|
||||
|
||||
|
||||
1.2 connectdata
|
||||
|
||||
A general idea in libcurl is to keep connections around in a connection
|
||||
"cache" after they have been used in case they will be used again and then
|
||||
re-use an existing one instead of creating a new as it creates a significant
|
||||
performance boost.
|
||||
|
||||
Each 'connectdata' identifies a single physical conncetion to a server. If
|
||||
the connection can't be kept alive, the connection will be closed after use
|
||||
and then this struct can be removed from the cache and freed.
|
||||
|
||||
Thus, the same SessionHandle can be used multiple times and each time select
|
||||
another connectdata struct to use for the connection. Keep this in mind, as
|
||||
it is then important to consider if options or choices are based on the
|
||||
connection or the SessionHandle.
|
||||
|
||||
Functions in libcurl will assume that connectdata->data points to the
|
||||
SessionHandle that uses this connection.
|
||||
|
||||
As a special complexity, some protocols supported by libcurl require a
|
||||
special disconnect procedure that is more than just shutting down the
|
||||
socket. It can involve sending one or more commands to the server before
|
||||
doing so. Since connections are kept in the connection cache after use, the
|
||||
original SessionHandle may no longer be around when the time comes to shut
|
||||
down a particular connection. For this purpose, libcurl holds a special
|
||||
dummy 'closure_handle' SessionHandle in the Curl_multi struct to
|
||||
|
||||
FTP uses two TCP connections for a typical transfer but it keeps both in
|
||||
this single struct and thus can be considered a single connection for most
|
||||
internal concerns.
|
||||
|
||||
The libcurl source code generally use the name 'conn' for the variable that
|
||||
points to the connectdata.
|
||||
|
||||
|
||||
1.3 Curl_multi
|
||||
|
||||
Internally, the easy interface is implemented as a wrapper around multi
|
||||
interface functions. This makes everything multi interface.
|
||||
|
||||
Curl_multi is the multi handle struct exposed as "CURLM *" in external APIs.
|
||||
|
||||
This struct holds a list of SessionHandle structs that have been added to
|
||||
this handle with curl_multi_add_handle(). The start of the list is ->easyp
|
||||
and ->num_easy is a counter of added SessionHandles.
|
||||
|
||||
->msglist is a linked list of messages to send back when
|
||||
curl_multi_info_read() is called. Basically a node is added to that list
|
||||
when an individual SessionHandle's transfer has completed.
|
||||
|
||||
->hostcache points to the name cache. It is a hash table for looking up name
|
||||
to IP. The nodes have a limited life time in there and this cache is meant
|
||||
to reduce the time for when the same name is wanted within a short period of
|
||||
time.
|
||||
|
||||
->timetree points to a tree of SessionHandles, sorted by the remaining time
|
||||
until it should be checked - normally some sort of timeout. Each
|
||||
SessionHandle has one node in the tree.
|
||||
|
||||
->sockhash is a hash table to allow fast lookups of socket descriptor to
|
||||
which SessionHandle that uses that descriptor. This is necessary for the
|
||||
multi_socket API.
|
||||
|
||||
->conn_cache points to the connection cache. It keeps track of all
|
||||
connections that are kept after use. The cache has a maximum size.
|
||||
|
||||
->closure_handle is described in the 'connectdata' section.
|
||||
|
||||
The libcurl source code generally use the name 'multi' for the variable that
|
||||
points to the Curl_multi struct.
|
||||
|
||||
|
||||
1.4 Curl_handler
|
||||
|
||||
Each unique protocol that is supported by libcurl needs to provide at least
|
||||
one Curl_handler struct. It defines what the protocol is called and what
|
||||
functions the main code should call to deal with protocol specific issues.
|
||||
In general, there's a source file named [protocol].c in which there's a
|
||||
"struct Curl_handler Curl_handler_[protocol]" declared. In url.c there's
|
||||
then the main array with all individual Curl_handler structs pointed to from
|
||||
a single array which is scanned through when a URL is given to libcurl to
|
||||
work with.
|
||||
|
||||
->scheme is the URL scheme name, usually spelled out in uppercase. That's
|
||||
"HTTP" or "FTP" etc. SSL versions of the protcol need its own Curl_handler
|
||||
setup so HTTPS separate from HTTP.
|
||||
|
||||
->setup_connection is called to allow the protocol code to allocate protocol
|
||||
specific data that then gets associated with that SessionHandle for the rest
|
||||
of this transfer. It gets freed again at the end of the transfer. It will be
|
||||
called before the 'connectdata' for the transfer has been selected/created.
|
||||
Most protocols will allocate its private 'struct [PROTOCOL]' here and assign
|
||||
SessionHandle->req.protop to point to it.
|
||||
|
||||
->connect_it allows a protocol to do some specific actions after the TCP
|
||||
connect is done, that can still be considered part of the connection phase.
|
||||
|
||||
Some protocols will alter the connectdata->recv[] and connectdata->send[]
|
||||
function pointers in this function.
|
||||
|
||||
->connecting is similarly a function that keeps getting called as long as the
|
||||
protocol considers itself still in the connecting phase.
|
||||
|
||||
->do_it is the function called to issue the transfer request. What we call
|
||||
the DO action internally. If the DO is not enough and things need to be kept
|
||||
getting done for the entier DO sequence to complete, ->doing is then usually
|
||||
also provided. Each protocol that needs to do multiple commands or similar
|
||||
for do/doing need to implement their own state machines (see SCP, SFTP,
|
||||
FTP). Some protocols (only FTP and only due to historical reasons) has a
|
||||
separate piece of the DO state called DO_MORE.
|
||||
|
||||
->doing keeps getting called while issudeing the transfer request command(s)
|
||||
|
||||
->done gets called when the transfer is complete and DONE. That's after the
|
||||
main data has been transferred.
|
||||
|
||||
->do_more gets called doring the DO_MORE state. The FTP protocol uses this
|
||||
state when setting up the second connection.
|
||||
|
||||
->proto_getsock
|
||||
->doing_getsock
|
||||
->domore_getsock
|
||||
->perform_getsock
|
||||
Functions that return socket information. Which socket(s) to wait for which
|
||||
action(s) during the particular multi state.
|
||||
|
||||
->disconnect is called immediately before the TCP connection is shutdown.
|
||||
|
||||
->readwrite gets called during transfer to allow the protocol to do extra
|
||||
reads/writes
|
||||
|
||||
->defport is the default report TCP or UDP port this protocol uses
|
||||
|
||||
->protocol is one or more bits in the CURLPROTO_* set. The SSL versions have
|
||||
their "base" protocol set and then the SSL variation. Like "HTTP|HTTPS".
|
||||
|
||||
->flags is a bitmask with additional information about the protocol that will
|
||||
make it get treated differently by the generic engine:
|
||||
|
||||
PROTOPT_SSL - will make it connect and negotiate SSL
|
||||
|
||||
PROTOPT_DUAL - this protocol uses two connections
|
||||
|
||||
PROTOPT_CLOSEACTION - this protocol has actions to do before closing the
|
||||
connection. This flag is no longer used by code, yet still set for a bunch
|
||||
protocol handlers.
|
||||
|
||||
PROTOPT_DIRLOCK - "direction lock". The SSH protocols set this bit to
|
||||
limit which "direction" of socket actions that the main engine will
|
||||
concern itself about.
|
||||
|
||||
PROTOPT_NONETWORK - a protocol that doesn't use network (read file:)
|
||||
|
||||
PROTOPT_NEEDSPWD - this protocol needs a password and will use a default
|
||||
one unless one is provided
|
||||
|
||||
PROTOPT_NOURLQUERY - this protocol can't handle a query part on the URL
|
||||
(?foo=bar)
|
||||
|
||||
|
||||
1.5 conncache
|
||||
|
||||
Is a hash table with connections for later re-use. Each SessionHandle has
|
||||
a pointer to its connection cache. Each multi handle sets up a connection
|
||||
cache that all added SessionHandles share by default.
|
||||
|
||||
|
||||
1.6 Curl_share
|
||||
|
||||
The libcurl share API allocates a Curl_share struct, exposed to the external
|
||||
API as "CURLSH *".
|
||||
|
||||
The idea is that the struct can have a set of own versions of caches and
|
||||
pools and then by providing this struct in the CURLOPT_SHARE option, those
|
||||
specific SessionHandles will use the caches/pools that this share handle
|
||||
holds.
|
||||
|
||||
Then individual SessionHandle structs can be made to share specific things
|
||||
that they otherwise wouldn't, such as cookies.
|
||||
|
||||
The Curl_share struct can currently hold cookies, DNS cache and the SSL
|
||||
session cache.
|
||||
|
||||
|
||||
1.7 CookieInfo
|
||||
|
||||
This is the main cookie struct. It holds all known cookies and related
|
||||
information. Each SessionHandle has its own private CookieInfo even when
|
||||
they are added to a multi handle. They can be made to share cookies by using
|
||||
the share API.
|
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2013, 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,8 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
man_MANS = curl.1 curl-config.1 mk-ca-bundle.1
|
||||
man_MANS = curl.1 curl-config.1
|
||||
noinst_man_MANS = mk-ca-bundle.1
|
||||
GENHTMLPAGES = curl.html curl-config.html mk-ca-bundle.html
|
||||
PDFPAGES = curl.pdf curl-config.pdf mk-ca-bundle.pdf
|
||||
|
||||
@@ -36,7 +37,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
|
||||
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
|
||||
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
|
||||
$(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \
|
||||
MAIL-ETIQUETTE HTTP-COOKIES
|
||||
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS
|
||||
|
||||
MAN2HTML= roffit < $< >$@
|
||||
|
||||
|
32
docs/THANKS
32
docs/THANKS
@@ -21,6 +21,7 @@ Albert Choy
|
||||
Ale Vesely
|
||||
Alejandro Alvarez
|
||||
Aleksandar Milivojevic
|
||||
Aleksey Tulinov
|
||||
Alessandro Ghedini
|
||||
Alessandro Vesely
|
||||
Alex Bligh
|
||||
@@ -47,11 +48,13 @@ Amol Pattekar
|
||||
Amr Shahin
|
||||
Anatoli Tubman
|
||||
Anders Gustafsson
|
||||
Anders Havn
|
||||
Andi Jahja
|
||||
Andre Guibert de Bruet
|
||||
Andreas Damm
|
||||
Andreas Faerber
|
||||
Andreas Farber
|
||||
Andreas Malzahn
|
||||
Andreas Ntaflos
|
||||
Andreas Olsson
|
||||
Andreas Rieke
|
||||
@@ -69,6 +72,7 @@ Andrew Kurushin
|
||||
Andrew Moise
|
||||
Andrew Wansink
|
||||
Andrew de los Reyes
|
||||
Andrii Moiseiev
|
||||
Andrés García
|
||||
Andy Cedilnik
|
||||
Andy Serpa
|
||||
@@ -103,6 +107,7 @@ Ben Van Hof
|
||||
Ben Winslow
|
||||
Benbuck Nason
|
||||
Benjamin Gerard
|
||||
Benjamin Gilbert
|
||||
Benjamin Johnson
|
||||
Bernard Leak
|
||||
Bernhard Reutner-Fischer
|
||||
@@ -136,6 +141,7 @@ Bruce Mitchener
|
||||
Bruno de Carvalho
|
||||
Bryan Henderson
|
||||
Bryan Kemp
|
||||
Byrial Jensen
|
||||
Cameron Kaiser
|
||||
Camille Moncelier
|
||||
Caolan McNamara
|
||||
@@ -162,6 +168,7 @@ Christian Kurz
|
||||
Christian Robottom Reis
|
||||
Christian Schmitz
|
||||
Christian Vogt
|
||||
Christian Weisgerber
|
||||
Christophe Demory
|
||||
Christophe Legry
|
||||
Christopher Conroy
|
||||
@@ -234,6 +241,7 @@ David Odin
|
||||
David Phillips
|
||||
David Rosenstrauch
|
||||
David Shaw
|
||||
David Strauss
|
||||
David Tarendash
|
||||
David Thiel
|
||||
David Wright
|
||||
@@ -266,6 +274,7 @@ Douglas R. Horner
|
||||
Douglas Steinwand
|
||||
Dov Murik
|
||||
Duane Cathey
|
||||
Duncan
|
||||
Duncan Mac-Vicar Prett
|
||||
Dustin Boswell
|
||||
Dylan Ellicott
|
||||
@@ -274,6 +283,7 @@ Early Ehlinger
|
||||
Ebenezer Ikonne
|
||||
Edin Kadribasic
|
||||
Eduard Bloch
|
||||
Edward Rudd
|
||||
Edward Sheldrake
|
||||
Eelco Dolstra
|
||||
Eetu Ojanen
|
||||
@@ -291,15 +301,18 @@ Eric Lavigne
|
||||
Eric Melville
|
||||
Eric Mertens
|
||||
Eric Rautman
|
||||
Eric S. Raymond
|
||||
Eric Thelin
|
||||
Eric Vergnaud
|
||||
Eric Wong
|
||||
Eric Young
|
||||
Erick Nuwendam
|
||||
Erik Johansson
|
||||
Erwan Legrand
|
||||
Erwin Authried
|
||||
Eugene Kotlyarov
|
||||
Evan Jordan
|
||||
Evgeny Turnaev
|
||||
Eygene Ryabinkin
|
||||
Fabian Hiernaux
|
||||
Fabian Keil
|
||||
@@ -364,6 +377,7 @@ Gwenole Beauchesne
|
||||
Götz Babin-Ebell
|
||||
Hamish Mackenzie
|
||||
Hang Kin Lau
|
||||
Hang Su
|
||||
Hanno Kranzhoff
|
||||
Hans Steegers
|
||||
Hans-Jurgen May
|
||||
@@ -398,6 +412,7 @@ Immanuel Gregoire
|
||||
Ingmar Runge
|
||||
Ingo Ralf Blum
|
||||
Ingo Wilken
|
||||
Ishan SinghLevett
|
||||
Jack Zhang
|
||||
Jacky Lam
|
||||
Jacob Meuser
|
||||
@@ -419,6 +434,7 @@ Jan Koen Annot
|
||||
Jan Kunder
|
||||
Jan Schaumann
|
||||
Jan Van Boghout
|
||||
Jared Jennings
|
||||
Jared Lundell
|
||||
Jari Sundell
|
||||
Jason Glasgow
|
||||
@@ -433,6 +449,7 @@ Jean-Claude Chauve
|
||||
Jean-Francois Bertrand
|
||||
Jean-Louis Lemaire
|
||||
Jean-Marc Ranger
|
||||
Jean-Noel Rouvignac
|
||||
Jean-Philippe Barrette-LaPierre
|
||||
Jeff Connelly
|
||||
Jeff Johnson
|
||||
@@ -470,6 +487,7 @@ John Bradshaw
|
||||
John Crow
|
||||
John Dennis
|
||||
John E. Malmberg
|
||||
John Gardiner Myers
|
||||
John Janssen
|
||||
John Joseph Bachir
|
||||
John Kelly
|
||||
@@ -511,6 +529,7 @@ Julien Royer
|
||||
Jun-ichiro itojun Hagino
|
||||
Jurij Smakov
|
||||
Justin Fletcher
|
||||
Justin Karneges
|
||||
Jörg Mueller-Tolk
|
||||
Jörn Hartroth
|
||||
Kai Engert
|
||||
@@ -544,6 +563,7 @@ Kimmo Kinnunen
|
||||
Kjell Ericson
|
||||
Kjetil Jacobsen
|
||||
Klevtsov Vadim
|
||||
Konstantin Isakov
|
||||
Kris Kennaway
|
||||
Krishnendu Majumdar
|
||||
Krister Johansen
|
||||
@@ -556,6 +576,7 @@ Larry Fahnoe
|
||||
Lars Buitinck
|
||||
Lars Gustafsson
|
||||
Lars J. Aas
|
||||
Lars Johannesen
|
||||
Lars Nilsson
|
||||
Lars Torben Wilson
|
||||
Lau Hang Kin
|
||||
@@ -578,6 +599,7 @@ Loren Kirkby
|
||||
Luca Altea
|
||||
Luca Alteas
|
||||
Lucas Adamski
|
||||
Ludovico Cavedon
|
||||
Lukasz Czekierda
|
||||
Luke Amery
|
||||
Luke Call
|
||||
@@ -589,6 +611,7 @@ Mandy Wu
|
||||
Manfred Schwarb
|
||||
Manuel Massing
|
||||
Marc Boucher
|
||||
Marc Doughty
|
||||
Marc Hoersken
|
||||
Marc Kleine-Budde
|
||||
Marcel Raad
|
||||
@@ -668,12 +691,14 @@ Michal Gorny
|
||||
Michal Kowalczyk
|
||||
Michal Marek
|
||||
Michele Bini
|
||||
Miguel Angel
|
||||
Mihai Ionescu
|
||||
Mikael Johansson
|
||||
Mikael Sennerholm
|
||||
Mike Bytnar
|
||||
Mike Crowe
|
||||
Mike Dobbs
|
||||
Mike Giancola
|
||||
Mike Hommey
|
||||
Mike Power
|
||||
Mike Protts
|
||||
@@ -684,6 +709,7 @@ Mohamed Lrhazi
|
||||
Mohun Biswas
|
||||
Moonesamy
|
||||
Myk Taylor
|
||||
Nach M. S.
|
||||
Nathan Coulter
|
||||
Nathan O'Sullivan
|
||||
Nathanael Nerode
|
||||
@@ -752,6 +778,7 @@ Pedro Neves
|
||||
Pete Su
|
||||
Peter Bray
|
||||
Peter Forret
|
||||
Peter Gal
|
||||
Peter Heuchert
|
||||
Peter Hjalmarsson
|
||||
Peter Korsgaard
|
||||
@@ -804,6 +831,7 @@ Reinout van Schouwen
|
||||
Renato Botelho
|
||||
Renaud Chaillat
|
||||
Renaud Duhaut
|
||||
Renaud Guillard
|
||||
Rene Bernhardt
|
||||
Rene Rebe
|
||||
Reuven Wachtfogel
|
||||
@@ -903,6 +931,7 @@ Stan van de Burgt
|
||||
Stanislav Ivochkin
|
||||
Stefan Esser
|
||||
Stefan Krause
|
||||
Stefan Neis
|
||||
Stefan Teleman
|
||||
Stefan Tomanek
|
||||
Stefan Ulrich
|
||||
@@ -950,6 +979,7 @@ Tim Harder
|
||||
Tim Heckman
|
||||
Tim Newsome
|
||||
Tim Sneddon
|
||||
Timo Sirainen
|
||||
Tinus van den Berg
|
||||
Tobias Rundström
|
||||
Toby Peterson
|
||||
@@ -1013,6 +1043,7 @@ Wez Furlong
|
||||
Wilfredo Sanchez
|
||||
Willem Sparreboom
|
||||
Wojciech Zwiefka
|
||||
Wouter Van Rooy
|
||||
Wu Yongzheng
|
||||
Xavier Bouchoux
|
||||
Yamada Yasuharu
|
||||
@@ -1024,6 +1055,7 @@ Yuriy Sosov
|
||||
Yves Arrouye
|
||||
Yves Lejeune
|
||||
Zdenek Pavlas
|
||||
Zekun Ni
|
||||
Zmey Petroff
|
||||
Zvi Har'El
|
||||
nk
|
||||
|
37
docs/TODO
37
docs/TODO
@@ -16,8 +16,8 @@
|
||||
1.3 struct lifreq
|
||||
1.4 signal-based resolver timeouts
|
||||
1.5 get rid of PATH_MAX
|
||||
1.6 progress callback without doubles
|
||||
1.7 Happy Eyeball dual stack connect
|
||||
1.6 Happy Eyeball dual stack connect
|
||||
1.7 Modified buffer size approach
|
||||
|
||||
2. libcurl - multi interface
|
||||
2.1 More non-blocking
|
||||
@@ -157,16 +157,7 @@
|
||||
we need libssh2 to properly tell us when we pass in a too small buffer and
|
||||
its current API (as of libssh2 1.2.7) doesn't.
|
||||
|
||||
1.6 progress callback without doubles
|
||||
|
||||
The progress callback was introduced way back in the days and the choice to
|
||||
use doubles in the arguments was possibly good at the time. Today the doubles
|
||||
only confuse users and make the amounts less precise. We should introduce
|
||||
another progress callback option that take precedence over the old one and
|
||||
have both co-exist for a forseeable time until we can remove the double-using
|
||||
one.
|
||||
|
||||
1.7 Happy Eyeball dual stack connect
|
||||
1.6 Happy Eyeball dual stack connect
|
||||
|
||||
In order to make alternative technologies not suffer when transitioning, like
|
||||
when introducing IPv6 as an alternative to IPv4 and there are more than one
|
||||
@@ -178,6 +169,28 @@
|
||||
|
||||
http://tools.ietf.org/html/rfc6555
|
||||
|
||||
1.7 Modified buffer size approach
|
||||
|
||||
Current libcurl allocates a fixed 16K size buffer for download and an
|
||||
additional 16K for upload. They are always unconditionally part of the easy
|
||||
handle. If CRLF translations are requested, an additional 32K "scratch
|
||||
buffer" is allocated. A total of 64K transfer buffers in the worst case.
|
||||
|
||||
First, while the handles are not actually in use these buffers could be freed
|
||||
so that lingering handles just kept in queues or whatever waste less memory.
|
||||
|
||||
Secondly, SFTP is a protocol that needs to handle many ~30K blocks at once
|
||||
since each need to be individually acked and therefore libssh2 must be
|
||||
allowed to send (or receive) many separate ones in parallel to achieve high
|
||||
transfer speeds. A current libcurl build with a 16K buffer makes that
|
||||
impossible, but one with a 512K buffer will reach MUCH faster transfers. But
|
||||
allocating 512K unconditionally for all buffers just in case they would like
|
||||
to do fast SFTP transfers at some point is not a good solution either.
|
||||
|
||||
Dynamically allocate buffer size depending on protocol in use in combination
|
||||
with freeing it after each individual transfer? Other suggestions?
|
||||
|
||||
|
||||
2. libcurl - multi interface
|
||||
|
||||
2.1 More non-blocking
|
||||
|
28
docs/curl.1
28
docs/curl.1
@@ -230,7 +230,9 @@ server sends an unsupported encoding, curl will report an error.
|
||||
.IP "--connect-timeout <seconds>"
|
||||
Maximum time in seconds that you allow the connection to the server to take.
|
||||
This only limits the connection phase, once curl has connected this option is
|
||||
of no more use. See also the \fI-m, --max-time\fP option.
|
||||
of no more use. Since 7.32.0, this option accepts decimal values, but the
|
||||
actual timeout will decrease in accuracy as the specified timeout increases in
|
||||
decimal precision. See also the \fI-m, --max-time\fP option.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "--create-dirs"
|
||||
@@ -393,7 +395,10 @@ nickname contains ":", it needs to be preceded by "\\" so that it is not
|
||||
recognized as password delimiter. If the nickname contains "\\", it needs to
|
||||
be escaped as "\\\\" so that it is not recognized as an escape character.
|
||||
|
||||
(iOS and Mac OS X only) If curl is built against Secure Transport, then the certificate string must match the name of a certificate that's in the system or user keychain. The private key corresponding to the certificate, and certificate chain (if any), must also be present in the keychain.
|
||||
(iOS and Mac OS X only) If curl is built against Secure Transport, then the
|
||||
certificate string must match the name of a certificate that's in the system or
|
||||
user keychain. The private key corresponding to the certificate, and
|
||||
certificate chain (if any), must also be present in the keychain.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "--engine <name>"
|
||||
@@ -810,7 +815,10 @@ Basic authentication).
|
||||
.IP "-m, --max-time <seconds>"
|
||||
Maximum time in seconds that you allow the whole operation to take. This is
|
||||
useful for preventing your batch jobs from hanging for hours due to slow
|
||||
networks or links going down. See also the \fI--connect-timeout\fP option.
|
||||
networks or links going down. Since 7.32.0, this option accepts decimal
|
||||
values, but the actual timeout will decrease in accuracy as the specified
|
||||
timeout increases in decimal precision. See also the \fI--connect-timeout\fP
|
||||
option.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "--mail-auth <address>"
|
||||
@@ -1043,6 +1051,13 @@ ubiquitous 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 "--post303"
|
||||
(HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert POST requests
|
||||
into GET requests when following a 303 redirection. The non-RFC behaviour is
|
||||
ubiquitous 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.26.0)
|
||||
.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
|
||||
@@ -1280,6 +1295,9 @@ If this option is used several times, the last one will be used.
|
||||
Silent or quiet mode. Don't show progress meter or error messages. Makes Curl
|
||||
mute. It will still output the data you ask for, potentially even to the
|
||||
terminal/stdout unless you redirect it.
|
||||
.IP "--sasl-ir"
|
||||
Enable initial response in SASL authentication.
|
||||
(Added in 7.31.0)
|
||||
.IP "-S, --show-error"
|
||||
When used with \fI-s\fP it makes curl show an error message if it fails.
|
||||
.IP "--ssl"
|
||||
@@ -1675,7 +1693,7 @@ If this option is used several times, the last one will be used.
|
||||
|
||||
.IP "--xattr"
|
||||
When saving output to a file, this option tells curl to store certain file
|
||||
metadata in extened file attributes. Currently, the URL is stored in the
|
||||
metadata in extended file attributes. Currently, the URL is stored in the
|
||||
xdg.origin.url attribute and, for HTTP, the content type is stored in
|
||||
the mime_type attribute. If the file system does not support extended
|
||||
attributes, a warning is issued.
|
||||
@@ -1695,7 +1713,7 @@ speed-time seconds it gets aborted. speed-time is set with \fI-y\fP and is 30
|
||||
if not set.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-z/--time-cond <date expression>|<file>"
|
||||
.IP "-z, --time-cond <date expression>|<file>"
|
||||
(HTTP/FTP) Request a file that has been modified later than the given time and
|
||||
date, or one that has been modified before that time. The <date expression>
|
||||
can be all sorts of date strings or if it doesn't match any internal ones, it
|
||||
|
@@ -5,8 +5,7 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
|
||||
persistant post-callback postit2 sepheaders simple simplepost simplessl \
|
||||
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
|
||||
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
|
||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget \
|
||||
usercertinmem
|
||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget
|
||||
|
||||
# These examples require external dependencies that may not be commonly
|
||||
# available on POSIX systems, so don't bother attempting to compile them here.
|
||||
@@ -14,4 +13,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
|
||||
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
|
||||
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
|
||||
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
|
||||
multi-uv.c xmlstream.c
|
||||
multi-uv.c xmlstream.c usercertinmem.c
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -30,9 +30,10 @@ struct myprogress {
|
||||
CURL *curl;
|
||||
};
|
||||
|
||||
static int progress(void *p,
|
||||
double dltotal, double dlnow,
|
||||
double ultotal, double ulnow)
|
||||
/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
|
||||
static int xferinfo(void *p,
|
||||
curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow)
|
||||
{
|
||||
struct myprogress *myp = (struct myprogress *)p;
|
||||
CURL *curl = myp->curl;
|
||||
@@ -48,7 +49,9 @@ static int progress(void *p,
|
||||
fprintf(stderr, "TOTAL TIME: %f \r\n", curtime);
|
||||
}
|
||||
|
||||
fprintf(stderr, "UP: %g of %g DOWN: %g of %g\r\n",
|
||||
fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
|
||||
" DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
|
||||
"\r\n",
|
||||
ulnow, ultotal, dlnow, dltotal);
|
||||
|
||||
if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
|
||||
@@ -56,6 +59,19 @@ static int progress(void *p,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */
|
||||
static int older_progress(void *p,
|
||||
double dltotal, double dlnow,
|
||||
double ultotal, double ulnow)
|
||||
{
|
||||
return xferinfo(p,
|
||||
(curl_off_t)dltotal,
|
||||
(curl_off_t)dlnow,
|
||||
(curl_off_t)ultotal,
|
||||
(curl_off_t)ulnow);
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
@@ -68,9 +84,28 @@ int main(void)
|
||||
prog.curl = curl;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/");
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress);
|
||||
/* pass the struct pointer into the progress function */
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x072000
|
||||
/* xferinfo was introduced in 7.32.0, no earlier libcurl versions will
|
||||
compile as they won't have the symbols around.
|
||||
|
||||
If built with a newer libcurl, but running with an older libcurl:
|
||||
curl_easy_setopt() will fail in run-time trying to set the new
|
||||
callback, making the older callback get used.
|
||||
|
||||
New libcurls will prefer the new callback and instead use that one even
|
||||
if both callbacks are set. */
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
|
||||
/* pass the struct pointer into the xferinfo function, note that this is
|
||||
an alias to CURLOPT_PROGRESSDATA */
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
|
||||
#endif
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
|
@@ -232,7 +232,7 @@ Pass a pointer to a char pointer to receive a pointer to a string holding the
|
||||
most recent RTSP Session ID.
|
||||
|
||||
Applications wishing to resume an RTSP session on another connection should
|
||||
retreive this info before closing the active connection.
|
||||
retrieve this info before closing the active connection.
|
||||
.IP CURLINFO_RTSP_CLIENT_CSEQ
|
||||
Pass a pointer to a long to receive the next CSeq that will be used by the
|
||||
application.
|
||||
@@ -244,7 +244,7 @@ by the application.
|
||||
unimplemented).\fP
|
||||
|
||||
Applications wishing to resume an RTSP session on another connection should
|
||||
retreive this info before closing the active connection.
|
||||
retrieve this info before closing the active connection.
|
||||
.IP CURLINFO_RTSP_CSEQ_RECV
|
||||
Pass a pointer to a long to receive the most recently received CSeq from the
|
||||
server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2013, 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,6 +68,18 @@ code means something wrong occurred after the new state was set. See the
|
||||
.SH AVAILABILITY
|
||||
This function was added in libcurl 7.18.0. Before this version, there was no
|
||||
explicit support for pausing transfers.
|
||||
.SH "USAGE WITH THE MULTI-SOCKET INTERFACE"
|
||||
Before libcurl 7.32.0, when a specific handle was unpaused with this function,
|
||||
there was no particular forced rechecking or similar of the socket's state,
|
||||
which made the continuation of the transfer get delayed until next
|
||||
multi-socket call invoke or even longer. Alternatively, the user could
|
||||
forcibly call for example curl_multi_socket_all(3) - with a rather hefty
|
||||
performance penalty.
|
||||
|
||||
Starting in libcurl 7.32.0, unpausing a transfer will schedule a timeout
|
||||
trigger for that handle 1 millisecond into the future, so that a
|
||||
curl_multi_socket_action( ... CURL_SOCKET_TIMEOUT) can be used immediately
|
||||
afterwards to get the transfer going again as desired.
|
||||
.SH "MEMORY USE"
|
||||
When pausing a read by returning the magic return code from a write callback,
|
||||
the read data is already in libcurl's internal buffers so it'll have to keep
|
||||
|
@@ -377,10 +377,54 @@ function that performs transfers.
|
||||
|
||||
\fICURLOPT_NOPROGRESS\fP must be set to 0 to make this function actually
|
||||
get called.
|
||||
.IP CURLOPT_XFERINFOFUNCTION
|
||||
Pass a pointer to a function that matches the following prototype:
|
||||
|
||||
.nf
|
||||
\fBint function(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow);\fP
|
||||
.fi
|
||||
|
||||
This function gets called by libcurl instead of its internal equivalent with a
|
||||
frequent interval. While data is being transferred it will be called very
|
||||
frequently, and during slow periods like when nothing is being transferred it
|
||||
can slow down to about one call per second.
|
||||
|
||||
\fIclientp\fP is the pointer set with \fICURLOPT_XFERINFODATA\fP, it is only
|
||||
passed along from the application to the callback.
|
||||
|
||||
The callback gets told how much data libcurl will transfer and has
|
||||
transferred, in number of bytes. \fIdltotal\fP is the total number of bytes
|
||||
libcurl expects to download in this transfer. \fIdlnow\fP is the number of
|
||||
bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl
|
||||
expects to upload in this transfer. \fIulnow\fP is the number of bytes
|
||||
uploaded so far.
|
||||
|
||||
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). Many times
|
||||
the callback will be called one or more times first, before it knows the data
|
||||
sizes so a program must be made to handle that.
|
||||
|
||||
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
|
||||
function that performs transfers.
|
||||
|
||||
\fICURLOPT_NOPROGRESS\fP must be set to 0 to make this function actually
|
||||
get called.
|
||||
|
||||
(Added in 7.32.0)
|
||||
.IP CURLOPT_PROGRESSDATA
|
||||
Pass a pointer that will be untouched by libcurl and passed as the first
|
||||
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
|
||||
The default value of this parameter is unspecified.
|
||||
.IP CURLOPT_XFERINFODATA
|
||||
Pass a pointer that will be untouched by libcurl and passed as the first
|
||||
argument in the progress callback set with \fICURLOPT_XFERINFOFUNCTION\fP.
|
||||
The default value of this parameter is unspecified. This option is an alias
|
||||
for CURLOPT_PROGRESSDATA. (Added in 7.32.0)
|
||||
.IP CURLOPT_HEADERFUNCTION
|
||||
Pass a pointer to a function that matches the following prototype:
|
||||
\fBsize_t function( void *ptr, size_t size, size_t nmemb, void
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2013, 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
|
||||
@@ -29,9 +29,9 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
Adds a standard easy handle to the multi stack. This function call will make
|
||||
this \fImulti_handle\fP control the specified \fIeasy_handle\fP.
|
||||
Furthermore, libcurl now initiates the connection associated with the
|
||||
specified \fIeasy_handle\fP.
|
||||
this \fImulti_handle\fP control the specified \fIeasy_handle\fP. Furthermore,
|
||||
libcurl now initiates the connection associated with the specified
|
||||
\fIeasy_handle\fP.
|
||||
|
||||
When an easy handle has been added to a multi stack, you can not and you must
|
||||
not use \fIcurl_easy_perform(3)\fP on that handle!
|
||||
@@ -41,6 +41,12 @@ cache (CURLOPT_DNS_USE_GLOBAL_CACHE), it will be made to use the DNS cache
|
||||
that is shared between all easy handles within the multi handle when
|
||||
\fIcurl_multi_add_handle(3)\fP is called.
|
||||
|
||||
If you have CURLMOPT_TIMERFUNCTION set in the multi handle (and you really
|
||||
should if you're working event-based with \fIcurl_multi_socket_action(3)\fP
|
||||
and friends), that callback will be called from within this function to ask
|
||||
for an updated timer so that your main event loop will get the activity on
|
||||
this handle to get started.
|
||||
|
||||
The easy handle will remain added until you remove it again with
|
||||
\fIcurl_multi_remove_handle(3)\fP. You should remove the easy handle from the
|
||||
multi stack before you terminate first the easy handle and then the multi
|
||||
|
@@ -428,7 +428,7 @@ CURLOPT_POSTREDIR 7.19.1
|
||||
CURLOPT_PREQUOTE 7.9.5
|
||||
CURLOPT_PRIVATE 7.10.3
|
||||
CURLOPT_PROGRESSDATA 7.1
|
||||
CURLOPT_PROGRESSFUNCTION 7.1
|
||||
CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
|
||||
CURLOPT_PROTOCOLS 7.19.4
|
||||
CURLOPT_PROXY 7.1
|
||||
CURLOPT_PROXYAUTH 7.10.7
|
||||
@@ -525,6 +525,8 @@ CURLOPT_WRITEDATA 7.9.7
|
||||
CURLOPT_WRITEFUNCTION 7.1
|
||||
CURLOPT_WRITEHEADER 7.1
|
||||
CURLOPT_WRITEINFO 7.1
|
||||
CURLOPT_XFERINFODATA 7.32.0
|
||||
CURLOPT_XFERINFOFUNCTION 7.32.0
|
||||
CURLPAUSE_ALL 7.18.0
|
||||
CURLPAUSE_CONT 7.18.0
|
||||
CURLPAUSE_RECV 7.18.0
|
||||
|
@@ -60,11 +60,16 @@ unlink (remove) certdata.txt after processing
|
||||
be verbose and print out processed CAs
|
||||
.SH EXIT STATUS
|
||||
Returns 0 on success. Returns 1 if it fails to download data.
|
||||
.SH CERTDATA FORMAT
|
||||
The file format used by Mozilla for this trust information seems to be documented here:
|
||||
.nf
|
||||
http://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html
|
||||
.fi
|
||||
.SH SEE ALSO
|
||||
.BR curl (1)
|
||||
.SH HISTORY
|
||||
\fBmk-ca-bundle\fP is a command line tool that is shipped as part of every
|
||||
curl and libcurl release (see http://curl.haxx.se/). It was originally based
|
||||
on the parse-certs script written by Roland Krikava and was later much
|
||||
improved by Guenter Knauf. This manual page was written by Jan Schaumann
|
||||
\&<jschauma@netmeister.org>.
|
||||
improved by Guenter Knauf. This manual page was initially written by Jan
|
||||
Schaumann \&<jschauma@netmeister.org>.
|
||||
|
@@ -156,12 +156,22 @@ struct curl_httppost {
|
||||
HTTPPOST_CALLBACK posts */
|
||||
};
|
||||
|
||||
/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
|
||||
deprecated but was the only choice up until 7.31.0 */
|
||||
typedef int (*curl_progress_callback)(void *clientp,
|
||||
double dltotal,
|
||||
double dlnow,
|
||||
double ultotal,
|
||||
double ulnow);
|
||||
|
||||
/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
|
||||
7.32.0, it avoids floating point and provides more detailed information. */
|
||||
typedef int (*curl_xferinfo_callback)(void *clientp,
|
||||
curl_off_t dltotal,
|
||||
curl_off_t dlnow,
|
||||
curl_off_t ultotal,
|
||||
curl_off_t ulnow);
|
||||
|
||||
#ifndef CURL_MAX_WRITE_SIZE
|
||||
/* Tests have proven that 20K is a very bad buffer size for uploads on
|
||||
Windows, while 16K for some odd reason performed a lot better.
|
||||
@@ -968,13 +978,16 @@ typedef enum {
|
||||
|
||||
/* 55 = OBSOLETE */
|
||||
|
||||
/* Function that will be called instead of the internal progress display
|
||||
/* DEPRECATED
|
||||
* Function that will be called instead of the internal progress display
|
||||
* function. This function should be defined as the curl_progress_callback
|
||||
* prototype defines. */
|
||||
CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
|
||||
|
||||
/* Data passed to the progress callback */
|
||||
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
|
||||
callbacks */
|
||||
CINIT(PROGRESSDATA, OBJECTPOINT, 57),
|
||||
#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
|
||||
|
||||
/* We want the referrer field set automatically when following locations */
|
||||
CINIT(AUTOREFERER, LONG, 58),
|
||||
@@ -1533,6 +1546,11 @@ typedef enum {
|
||||
/* Enable/disable SASL initial response */
|
||||
CINIT(SASL_IR, LONG, 218),
|
||||
|
||||
/* Function that will be called instead of the internal progress display
|
||||
* function. This function should be defined as the curl_xferinfo_callback
|
||||
* prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
|
||||
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
|
@@ -30,12 +30,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.31.0-DEV"
|
||||
#define LIBCURL_VERSION "7.32.0-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 31
|
||||
#define LIBCURL_VERSION_MINOR 32
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@@ -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 0x071f00
|
||||
#define LIBCURL_VERSION_NUM 0x072000
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
@@ -94,6 +94,10 @@ add_library(
|
||||
${HHEADERS} ${CSOURCES}
|
||||
)
|
||||
|
||||
if(MSVC AND CURL_STATICLIB)
|
||||
set_target_properties(${LIB_NAME} PROPERTIES STATIC_LIBRARY_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${LIB_NAME} ${CURL_LIBS})
|
||||
|
||||
if(WIN32)
|
||||
@@ -108,14 +112,6 @@ setup_curl_dependencies(${LIB_NAME})
|
||||
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
|
||||
|
||||
if(MSVC)
|
||||
if(NOT BUILD_RELEASE_DEBUG_DIRS)
|
||||
# Ugly workaround to remove the "/debug" or "/release" in each output
|
||||
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "../")
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "../")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(NOT CURL_STATICLIB)
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
|
||||
|
@@ -141,7 +141,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING)
|
||||
endif
|
||||
|
||||
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
|
||||
libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LIBCURL_LIBS)
|
||||
libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
|
||||
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
|
||||
|
||||
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
|
||||
|
@@ -52,7 +52,7 @@ LDFLAGS = -q -lq -laa -tWD
|
||||
SRCDIR = .
|
||||
OBJDIR = .\BCC_objs
|
||||
INCDIRS = -I.;..\include
|
||||
LINKLIB = $(BCCDIR)\lib\cw32mt.lib
|
||||
LINKLIB = $(BCCDIR)\lib\cw32mt.lib $(BCCDIR)\lib\ws2_32.lib
|
||||
DEFINES = -DNDEBUG -DWIN32 -DBUILDING_LIBCURL
|
||||
|
||||
# By default SSPI support is enabled for BCC
|
||||
@@ -88,8 +88,24 @@ LINKLIB = $(LINKLIB) $(OPENSSL_PATH)\out32\ssleay32.lib $(OPENSSL_PATH)\out32\l
|
||||
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||
!include Makefile.inc
|
||||
|
||||
OBJECTS = $(CSOURCES:.c=.obj)
|
||||
PREPROCESSED = $(CSOURCES:.c=.int)
|
||||
# Borland's command line librarian program TLIB version 4.5 is not capable
|
||||
# of building a library when any of its objects contains an hypen in its
|
||||
# name, due to a command line parsing bug. In order to workaround this, we
|
||||
# build source files with hyphens in their name as objects with underscores
|
||||
# using explicit compilation build rules instead of implicit ones.
|
||||
|
||||
NOHYPHEN = $(CSOURCES:-=_)
|
||||
|
||||
OBJECTS = $(NOHYPHEN:.c=.obj)
|
||||
PREPROCESSED = $(NOHYPHEN:.c=.int)
|
||||
|
||||
# Borland's command line compiler (BCC32) version 5.5.1 integrated
|
||||
# preprocessor has a bug which results in silently generating wrong
|
||||
# definitions for libcurl macros such as CURL_OFF_T_C, on the other
|
||||
# hand Borland's command line preprocessor (CPP32) version 5.5.1 does
|
||||
# not have the bug and achieves proper results. In order to avoid the
|
||||
# silent bug we first preprocess source files and later compile the
|
||||
# preprocessed result.
|
||||
|
||||
.c.obj:
|
||||
@-$(RM) $(@R).int
|
||||
@@ -98,6 +114,21 @@ PREPROCESSED = $(CSOURCES:.c=.int)
|
||||
|
||||
all: $(OBJDIR) $(LIBCURL_LIB) $(LIBCURL_DLL)
|
||||
|
||||
asyn_ares.obj: asyn-ares.c
|
||||
@-$(RM) $(@R).int
|
||||
$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
|
||||
$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
|
||||
|
||||
asyn_thread.obj: asyn-thread.c
|
||||
@-$(RM) $(@R).int
|
||||
$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
|
||||
$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
|
||||
|
||||
non_ascii.obj: non-ascii.c
|
||||
@-$(RM) $(@R).int
|
||||
$(PP_CMD) $(CC_FLAGS) $(INCDIRS) $(DEFINES) -o$(@R).int $(?)
|
||||
$(CC_CMD) $(CC_FLAGS) -o$(@) $(@R).int
|
||||
|
||||
clean:
|
||||
cd $(OBJDIR)
|
||||
@-$(RM) $(OBJECTS)
|
||||
@@ -122,7 +153,10 @@ $(LIBCURL_LIB): $(OBJECTS)
|
||||
$(LIBCURL_DLL) $(LIBCURL_IMPLIB): $(OBJECTS) $(LINKLIB)
|
||||
@-$(RM) $(LIBCURL_DLL)
|
||||
@-$(RM) $(LIBCURL_IMPLIB)
|
||||
$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) $**
|
||||
$(LD) $(LDFLAGS) -e$(LIBCURL_DLL) @&&!
|
||||
$(**: = ^
|
||||
)
|
||||
!
|
||||
$(IMPLIB) $(LIBCURL_IMPLIB) $(LIBCURL_DLL)
|
||||
|
||||
|
||||
|
@@ -13,7 +13,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.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 md4.c md5.c curl_rand.c \
|
||||
content_encoding.c share.c http_digest.c md4.c md5.c \
|
||||
http_negotiate.c inet_pton.c strtoofft.c strerror.c amigaos.c \
|
||||
hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c \
|
||||
select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c \
|
||||
@@ -25,12 +25,13 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
|
||||
curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c \
|
||||
curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c \
|
||||
hostcheck.c bundles.c conncache.c pipeline.c
|
||||
hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \
|
||||
gskit.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 \
|
||||
getinfo.h strequal.h krb4.h memdebug.h http_chunks.h \
|
||||
curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h \
|
||||
connect.h llist.h hash.h content_encoding.h share.h curl_md4.h \
|
||||
curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h \
|
||||
@@ -44,4 +45,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
||||
asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
|
||||
curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h \
|
||||
curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h \
|
||||
multihandle.h setup-vms.h pipeline.h
|
||||
multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h
|
||||
|
@@ -106,6 +106,7 @@ WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
|
||||
CCNODBG = cl.exe /O2 /DNDEBUG
|
||||
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
|
||||
CFLAGSSSL = /DUSE_SSLEAY /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
|
||||
CFLAGSWINSSL = /DUSE_SCHANNEL
|
||||
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
|
||||
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
|
||||
CFLAGS = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
|
||||
@@ -114,7 +115,7 @@ LNKDLL = link.exe /DLL
|
||||
LNKLIB = link.exe /lib
|
||||
LFLAGS = /nologo /machine:$(MACHINE)
|
||||
SSLLIBS = libeay32.lib ssleay32.lib
|
||||
ZLIBLIBSDLL= zdll.lib
|
||||
ZLIBLIBSDLL = zdll.lib
|
||||
ZLIBLIBS = zlib.lib
|
||||
WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
|
||||
CFLAGS = $(CFLAGS)
|
||||
@@ -189,6 +190,18 @@ CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
|
||||
######################
|
||||
# release-winssl-zlib
|
||||
|
||||
!IF "$(CFG)" == "release-winssl-zlib"
|
||||
TARGET = $(LIBCURL_STA_LIB_REL)
|
||||
DIROBJ = $(CFG)
|
||||
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
|
||||
LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
|
||||
CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
|
||||
######################
|
||||
# release-ssl-ssh2-zlib
|
||||
|
||||
@@ -515,7 +528,6 @@ X_OBJS= \
|
||||
$(DIROBJ)\curl_ntlm_core.obj \
|
||||
$(DIROBJ)\curl_ntlm_msgs.obj \
|
||||
$(DIROBJ)\curl_ntlm_wb.obj \
|
||||
$(DIROBJ)\curl_rand.obj \
|
||||
$(DIROBJ)\curl_rtmp.obj \
|
||||
$(DIROBJ)\curl_sasl.obj \
|
||||
$(DIROBJ)\curl_schannel.obj \
|
||||
@@ -523,6 +535,7 @@ X_OBJS= \
|
||||
$(DIROBJ)\curl_threads.obj \
|
||||
$(DIROBJ)\cyassl.obj \
|
||||
$(DIROBJ)\dict.obj \
|
||||
$(DIROBJ)\dotdot.obj \
|
||||
$(DIROBJ)\easy.obj \
|
||||
$(DIROBJ)\escape.obj \
|
||||
$(DIROBJ)\file.obj \
|
||||
|
@@ -315,6 +315,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ResolverResults *res = (struct ResolverResults *)
|
||||
conn->async.os_specific;
|
||||
CURLcode rc = CURLE_OK;
|
||||
|
||||
*dns = NULL;
|
||||
|
||||
@@ -325,19 +326,19 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
/* temp_ai ownership is moved to the connection, so we need not free-up
|
||||
them */
|
||||
res->temp_ai = NULL;
|
||||
destroy_async_data(&conn->async);
|
||||
if(!conn->async.dns) {
|
||||
failf(data, "Could not resolve %s: %s (%s)",
|
||||
conn->bits.proxy?"proxy":"host",
|
||||
conn->host.dispname,
|
||||
ares_strerror(conn->async.status));
|
||||
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
failf(data, "Could not resolve: %s (%s)",
|
||||
conn->async.hostname, ares_strerror(conn->async.status));
|
||||
rc = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
else
|
||||
*dns = conn->async.dns;
|
||||
|
||||
destroy_async_data(&conn->async);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -415,37 +416,12 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
|
||||
if(entry)
|
||||
*entry = conn->async.dns;
|
||||
|
||||
if(!conn->async.dns) {
|
||||
/* a name was not resolved */
|
||||
if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
|
||||
if(conn->bits.proxy) {
|
||||
failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname);
|
||||
rc = CURLE_COULDNT_RESOLVE_PROXY;
|
||||
}
|
||||
else {
|
||||
failf(data, "Resolving host timed out: %s", conn->host.dispname);
|
||||
rc = CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
}
|
||||
else if(conn->async.done) {
|
||||
if(conn->bits.proxy) {
|
||||
failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname,
|
||||
ares_strerror(conn->async.status));
|
||||
rc = CURLE_COULDNT_RESOLVE_PROXY;
|
||||
}
|
||||
else {
|
||||
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
|
||||
ares_strerror(conn->async.status));
|
||||
rc = CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
}
|
||||
else
|
||||
rc = CURLE_OPERATION_TIMEDOUT;
|
||||
|
||||
if(rc)
|
||||
/* close the connection, since we can't return failure here without
|
||||
cleaning up this connection properly */
|
||||
cleaning up this connection properly.
|
||||
TODO: remove this action from here, it is not a name resolver decision.
|
||||
*/
|
||||
conn->bits.close = TRUE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -614,8 +590,19 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
char *servers)
|
||||
{
|
||||
CURLcode result = CURLE_NOT_BUILT_IN;
|
||||
int ares_result;
|
||||
|
||||
/* If server is NULL or empty, this would purge all DNS servers
|
||||
* from ares library, which will cause any and all queries to fail.
|
||||
* So, just return OK if none are configured and don't actually make
|
||||
* any changes to c-ares. This lets c-ares use it's defaults, which
|
||||
* it gets from the OS (for instance from /etc/resolv.conf on Linux).
|
||||
*/
|
||||
if(!(servers && servers[0]))
|
||||
return CURLE_OK;
|
||||
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
int ares_result = ares_set_servers_csv(data->state.resolver, servers);
|
||||
ares_result = ares_set_servers_csv(data->state.resolver, servers);
|
||||
switch(ares_result) {
|
||||
case ARES_SUCCESS:
|
||||
result = CURLE_OK;
|
||||
@@ -632,7 +619,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
}
|
||||
#else /* too old c-ares version! */
|
||||
(void)data;
|
||||
(void)servers;
|
||||
(void)(ares_result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@@ -277,21 +277,27 @@
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H
|
||||
|
||||
|
||||
/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
|
||||
strdup(). */
|
||||
#define __cplusplus__strings__
|
||||
|
||||
/* Define if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define if you have the `strcmpi' function. */
|
||||
#undef HAVE_STRCMPI
|
||||
#define HAVE_STRCMPI
|
||||
|
||||
/* Define if you have the `stricmp' function. */
|
||||
#define HAVE_STRICMP
|
||||
|
||||
/* Define if you have the `strdup' function. */
|
||||
#undef HAVE_STRDUP
|
||||
#define HAVE_STRDUP
|
||||
|
||||
|
||||
/* Define if you have the `strftime' function. */
|
||||
#define HAVE_STRFTIME
|
||||
|
||||
/* Define if you have the `stricmp' function. */
|
||||
#undef HAVE_STRICMP
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H
|
||||
|
||||
@@ -525,6 +531,9 @@
|
||||
/* Define to use the QsoSSL package. */
|
||||
#define USE_QSOSSL
|
||||
|
||||
/* Define to use the GSKit package. */
|
||||
#undef USE_GSKIT
|
||||
|
||||
/* Use the system keyring as the default CA bundle. */
|
||||
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
|
||||
|
||||
|
@@ -1144,7 +1144,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
|
||||
if(sockfd == CURL_SOCKET_BAD) {
|
||||
/* no good connect was made */
|
||||
failf(data, "couldn't connect to %s at %s:%d",
|
||||
failf(data, "couldn't connect to %s at %s:%ld",
|
||||
conn->bits.proxy?"proxy":"host",
|
||||
conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
|
@@ -89,6 +89,7 @@ Example set of cookies:
|
||||
#include "strequal.h"
|
||||
#include "strtok.h"
|
||||
#include "sendf.h"
|
||||
#include "slist.h"
|
||||
#include "curl_memory.h"
|
||||
#include "share.h"
|
||||
#include "strtoofft.h"
|
||||
@@ -1232,9 +1233,9 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
|
||||
curl_slist_free_all(list);
|
||||
return NULL;
|
||||
}
|
||||
beg = curl_slist_append(list, line);
|
||||
free(line);
|
||||
beg = Curl_slist_append_nodup(list, line);
|
||||
if(!beg) {
|
||||
free(line);
|
||||
curl_slist_free_all(list);
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -38,9 +38,54 @@
|
||||
#include <Security/SecureTransport.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
|
||||
/* The Security framework has changed greatly between iOS and different OS X
|
||||
versions, and we will try to support as many of them as we can (back to
|
||||
Leopard and iOS 5) by using macros and weak-linking.
|
||||
|
||||
IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then
|
||||
you must build this project against the 10.8 SDK or later. */
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
|
||||
#error "The darwinssl back-end requires Leopard or later."
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
|
||||
|
||||
#define CURL_BUILD_IOS 0
|
||||
#define CURL_BUILD_MAC 1
|
||||
/* This is the maximum API level we are allowed to use when building: */
|
||||
#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
|
||||
#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
|
||||
#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
||||
/* These macros mean "the following code is present to allow runtime backward
|
||||
compatibility with at least this cat or earlier":
|
||||
(You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
|
||||
environmental variable.) */
|
||||
#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
|
||||
#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
|
||||
#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
|
||||
#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
|
||||
|
||||
#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
|
||||
#define CURL_BUILD_IOS 1
|
||||
#define CURL_BUILD_MAC 0
|
||||
#define CURL_BUILD_MAC_10_5 0
|
||||
#define CURL_BUILD_MAC_10_6 0
|
||||
#define CURL_BUILD_MAC_10_7 0
|
||||
#define CURL_BUILD_MAC_10_8 0
|
||||
#define CURL_SUPPORT_MAC_10_5 0
|
||||
#define CURL_SUPPORT_MAC_10_6 0
|
||||
#define CURL_SUPPORT_MAC_10_7 0
|
||||
#define CURL_SUPPORT_MAC_10_8 0
|
||||
|
||||
#else
|
||||
#error "The darwinssl back-end requires iOS or OS X."
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
|
||||
#if CURL_BUILD_MAC
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
@@ -61,16 +106,6 @@
|
||||
#define ioErr -36
|
||||
#define paramErr -50
|
||||
|
||||
/* In Mountain Lion and iOS 5, Apple made some changes to the API. They
|
||||
added TLS 1.1 and 1.2 support, and deprecated and replaced some
|
||||
functions. You need to build against the Mountain Lion or iOS 5 SDK
|
||||
or later to get TLS 1.1 or 1.2 support working in cURL. We'll weak-link
|
||||
to the newer functions and use them if present in the user's OS.
|
||||
|
||||
Builders: If you want TLS 1.1 and 1.2 but still want to retain support
|
||||
for older cats, don't forget to set the MACOSX_DEPLOYMENT_TARGET
|
||||
environmental variable prior to building cURL. */
|
||||
|
||||
/* The following two functions were ripped from Apple sample code,
|
||||
* with some modifications: */
|
||||
static OSStatus SocketRead(SSLConnectionRef connection,
|
||||
@@ -361,7 +396,7 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
|
||||
case TLS_DH_anon_WITH_AES_256_CBC_SHA:
|
||||
return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
#if defined(__MAC_10_6) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
|
||||
/* TLS 1.0 with ECDSA (RFC 4492) */
|
||||
case TLS_ECDH_ECDSA_WITH_NULL_SHA:
|
||||
return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
|
||||
@@ -438,8 +473,8 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
|
||||
case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
|
||||
return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
#endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
/* TLS 1.2 (RFC 5246) */
|
||||
case TLS_RSA_WITH_NULL_MD5:
|
||||
return "TLS_RSA_WITH_NULL_MD5";
|
||||
@@ -624,12 +659,12 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
|
||||
case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
|
||||
return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
|
||||
break;
|
||||
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
|
||||
}
|
||||
return "TLS_NULL_WITH_NULL_NULL";
|
||||
}
|
||||
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
|
||||
{
|
||||
int mib[2];
|
||||
@@ -658,7 +693,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
|
||||
*minor = atoi(os_version_minor);
|
||||
free(os_version);
|
||||
}
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
|
||||
/* Apple provides a myriad of ways of getting information about a certificate
|
||||
into a string. Some aren't available under iOS or newer cats. So here's
|
||||
@@ -668,37 +703,36 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
|
||||
{
|
||||
CFStringRef server_cert_summary = CFSTR("(null)");
|
||||
|
||||
#if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
|
||||
#if CURL_BUILD_IOS
|
||||
/* iOS: There's only one way to do this. */
|
||||
server_cert_summary = SecCertificateCopySubjectSummary(cert);
|
||||
#else
|
||||
#if defined(__MAC_10_7)
|
||||
#if CURL_BUILD_MAC_10_7
|
||||
/* Lion & later: Get the long description if we can. */
|
||||
if(SecCertificateCopyLongDescription != NULL)
|
||||
server_cert_summary =
|
||||
SecCertificateCopyLongDescription(NULL, cert, NULL);
|
||||
else
|
||||
#endif /* defined(__MAC_10_7) */
|
||||
#if defined(__MAC_10_6)
|
||||
#endif /* CURL_BUILD_MAC_10_7 */
|
||||
#if CURL_BUILD_MAC_10_6
|
||||
/* Snow Leopard: Get the certificate summary. */
|
||||
if(SecCertificateCopySubjectSummary != NULL)
|
||||
server_cert_summary = SecCertificateCopySubjectSummary(cert);
|
||||
else
|
||||
#endif /* defined(__MAC_10_6) */
|
||||
#endif /* CURL_BUILD_MAC_10_6 */
|
||||
/* Leopard is as far back as we go... */
|
||||
(void)SecCertificateCopyCommonName(cert, &server_cert_summary);
|
||||
#endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */
|
||||
#endif /* CURL_BUILD_IOS */
|
||||
return server_cert_summary;
|
||||
}
|
||||
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_7
|
||||
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
|
||||
deprecation warnings, so let's not compile this unless it's necessary: */
|
||||
static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||
SecIdentityRef *out_c_a_k)
|
||||
{
|
||||
OSStatus status = errSecItemNotFound;
|
||||
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
|
||||
deprecation warnings, so let's not compile this unless it's necessary: */
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||
SecKeychainAttributeList attr_list;
|
||||
SecKeychainAttribute attr;
|
||||
SecKeychainSearchRef search = NULL;
|
||||
@@ -730,22 +764,20 @@ static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||
|
||||
if(search)
|
||||
CFRelease(search);
|
||||
#else
|
||||
#pragma unused(label, out_c_a_k)
|
||||
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */
|
||||
return status;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_7 */
|
||||
|
||||
static OSStatus CopyIdentityWithLabel(char *label,
|
||||
SecIdentityRef *out_cert_and_key)
|
||||
{
|
||||
OSStatus status = errSecItemNotFound;
|
||||
|
||||
#if defined(__MAC_10_6) || defined(__IPHONE_2_0)
|
||||
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard. If it
|
||||
exists, let's use that to find the certificate. */
|
||||
if(SecItemCopyMatching != NULL) {
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
|
||||
kSecClassIdentity was introduced in Lion. If both exist, let's use them
|
||||
to find the certificate. */
|
||||
if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
|
||||
CFTypeRef keys[4];
|
||||
CFTypeRef values[4];
|
||||
CFDictionaryRef query_dict;
|
||||
@@ -774,15 +806,16 @@ static OSStatus CopyIdentityWithLabel(char *label,
|
||||
CFRelease(query_dict);
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
/* On Leopard, fall back to SecKeychainSearch. */
|
||||
#if CURL_SUPPORT_MAC_10_7
|
||||
/* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
|
||||
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_7 */
|
||||
}
|
||||
#elif (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
/* For developers building on Leopard, we have no choice but to fall back. */
|
||||
#elif CURL_SUPPORT_MAC_10_7
|
||||
/* For developers building on older cats, we have no choice but to fall back
|
||||
to SecKeychainSearch. */
|
||||
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||
#endif /* defined(__MAC_10_6) || defined(__IPHONE_2_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -796,19 +829,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
struct in6_addr addr;
|
||||
#else
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif /* ENABLE_IPV6 */
|
||||
size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
|
||||
SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
|
||||
char *ssl_sessionid;
|
||||
size_t ssl_sessionid_len;
|
||||
OSStatus err = noErr;
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
int darwinver_maj = 0, darwinver_min = 0;
|
||||
|
||||
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
|
||||
if(connssl->ssl_ctx)
|
||||
CFRelease(connssl->ssl_ctx);
|
||||
@@ -820,7 +853,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* The old ST API does not exist under iOS, so don't compile it: */
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
if(connssl->ssl_ctx)
|
||||
(void)SSLDisposeContext(connssl->ssl_ctx);
|
||||
err = SSLNewContext(false, &(connssl->ssl_ctx));
|
||||
@@ -828,7 +861,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
failf(data, "SSL: couldn't create a context: OSStatus %d", err);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
if(connssl->ssl_ctx)
|
||||
@@ -838,11 +871,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
failf(data, "SSL: couldn't create a context: OSStatus %d", err);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
|
||||
connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
|
||||
|
||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
if(SSLSetProtocolVersionMax != NULL) {
|
||||
switch(data->set.ssl.version) {
|
||||
case CURL_SSLVERSION_DEFAULT: default:
|
||||
@@ -858,12 +891,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
|
||||
err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
|
||||
if(err != noErr) {
|
||||
failf(data, "Your version of the OS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocolAll,
|
||||
false);
|
||||
@@ -899,12 +936,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol2,
|
||||
true);
|
||||
if(err != noErr) {
|
||||
failf(data, "Your version of the OS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
|
||||
@@ -924,9 +965,13 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol2,
|
||||
true);
|
||||
if(err != noErr) {
|
||||
failf(data, "Your version of the OS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
@@ -934,11 +979,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
break;
|
||||
}
|
||||
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
|
||||
|
||||
if(data->set.str[STRING_KEY]) {
|
||||
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
|
||||
"Transport. The private key must be in the Keychain.");
|
||||
"Transport. The private key must be in the Keychain.\n");
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
@@ -992,7 +1037,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
* fail to connect if the verification fails, or if it should continue
|
||||
* anyway. In the latter case the result of the verification is checked with
|
||||
* SSL_get_verify_result() below. */
|
||||
#if defined(__MAC_10_6) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
|
||||
/* Snow Leopard introduced the SSLSetSessionOption() function, but due to
|
||||
a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
|
||||
works, it doesn't work as expected under Snow Leopard or Lion.
|
||||
@@ -1001,11 +1046,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
(SecureTransport will always validate the certificate chain by
|
||||
default.) */
|
||||
/* (Note: Darwin 12.x.x is Mountain Lion.) */
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
if(SSLSetSessionOption != NULL && darwinver_maj >= 12) {
|
||||
#else
|
||||
if(SSLSetSessionOption != NULL) {
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
err = SSLSetSessionOption(connssl->ssl_ctx,
|
||||
kSSLSessionOptionBreakOnServerAuth,
|
||||
data->set.ssl.verifypeer?false:true);
|
||||
@@ -1015,14 +1060,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||
data->set.ssl.verifypeer?true:false);
|
||||
if(err != noErr) {
|
||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#else
|
||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||
@@ -1031,7 +1076,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
#endif /* defined(__MAC_10_6) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
|
||||
/* If this is a domain name and not an IP address, then configure SNI.
|
||||
* Also: the verifyhost setting influences SNI usage */
|
||||
@@ -1044,7 +1089,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
|
||||
strlen(conn->host.name));
|
||||
if(err != noErr) {
|
||||
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
|
||||
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
|
||||
err);
|
||||
}
|
||||
}
|
||||
@@ -1061,7 +1106,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
|
||||
&all_ciphers_count) == noErr) {
|
||||
for(i = 0UL ; i < all_ciphers_count ; i++) {
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_BUILD_MAC
|
||||
/* There's a known bug in early versions of Mountain Lion where ST's ECC
|
||||
ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
|
||||
Work around the problem here by disabling those ciphers if we are
|
||||
@@ -1070,7 +1115,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
switch(all_ciphers[i]) {
|
||||
/* Disable NULL ciphersuites: */
|
||||
case SSL_NULL_WITH_NULL_NULL:
|
||||
@@ -1303,7 +1348,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
infof(data, "TLS 1.0 connection using %s\n",
|
||||
TLSCipherNameForNumber(cipher));
|
||||
break;
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
case kTLSProtocol11:
|
||||
infof(data, "TLS 1.1 connection using %s\n",
|
||||
TLSCipherNameForNumber(cipher));
|
||||
@@ -1330,20 +1375,22 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
CFStringRef server_cert_summary;
|
||||
char server_cert_summary_c[128];
|
||||
CFArrayRef server_certs;
|
||||
CFArrayRef server_certs = NULL;
|
||||
SecCertificateRef server_cert;
|
||||
OSStatus err;
|
||||
CFIndex i, count;
|
||||
SecTrustRef trust;
|
||||
SecTrustRef trust = NULL;
|
||||
|
||||
/* There is no step 3!
|
||||
* Well, okay, if verbose mode is on, let's print the details of the
|
||||
* server certificates. */
|
||||
#if defined(__MAC_10_7) || defined(__IPHONE_5_0)
|
||||
#if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
#if CURL_BUILD_IOS
|
||||
#pragma unused(server_certs)
|
||||
err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
|
||||
if(err == noErr) {
|
||||
/* For some reason, SSLCopyPeerTrust() can return noErr and yet return
|
||||
a null trust, so be on guard for that: */
|
||||
if(err == noErr && trust) {
|
||||
count = SecTrustGetCertificateCount(trust);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = SecTrustGetCertificateAtIndex(trust, i);
|
||||
@@ -1369,7 +1416,9 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
if(SecTrustEvaluateAsync != NULL) {
|
||||
#pragma unused(server_certs)
|
||||
err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
|
||||
if(err == noErr) {
|
||||
/* For some reason, SSLCopyPeerTrust() can return noErr and yet return
|
||||
a null trust, so be on guard for that: */
|
||||
if(err == noErr && trust) {
|
||||
count = SecTrustGetCertificateCount(trust);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = SecTrustGetCertificateAtIndex(trust, i);
|
||||
@@ -1387,8 +1436,10 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
|
||||
if(err == noErr) {
|
||||
/* Just in case SSLCopyPeerCertificates() returns null too... */
|
||||
if(err == noErr && server_certs) {
|
||||
count = CFArrayGetCount(server_certs);
|
||||
for(i = 0L ; i < count ; i++) {
|
||||
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
|
||||
@@ -1406,8 +1457,9 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
CFRelease(server_certs);
|
||||
}
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
}
|
||||
#endif /* (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) */
|
||||
#endif /* CURL_BUILD_IOS */
|
||||
#else
|
||||
#pragma unused(trust)
|
||||
err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
|
||||
@@ -1427,7 +1479,7 @@ darwinssl_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
CFRelease(server_certs);
|
||||
}
|
||||
#endif /* defined(__MAC_10_7) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
|
||||
|
||||
connssl->connecting_state = ssl_connect_done;
|
||||
return CURLE_OK;
|
||||
@@ -1579,16 +1631,16 @@ void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
|
||||
|
||||
if(connssl->ssl_ctx) {
|
||||
(void)SSLClose(connssl->ssl_ctx);
|
||||
#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
if(SSLCreateContext != NULL)
|
||||
CFRelease(connssl->ssl_ctx);
|
||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
else
|
||||
(void)SSLDisposeContext(connssl->ssl_ctx);
|
||||
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||
#endif /* CURL_SUPPORT_MAC_10_8 */
|
||||
#else
|
||||
(void)SSLDisposeContext(connssl->ssl_ctx);
|
||||
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
||||
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
|
||||
connssl->ssl_ctx = NULL;
|
||||
}
|
||||
connssl->ssl_sockfd = 0;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012, Nick Zitzmann, <nickzman@gmail.com>.
|
||||
* Copyright (C) 2012 - 2013, Nick Zitzmann, <nickzman@gmail.com>.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -52,6 +52,10 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
|
||||
unsigned char *md5sum, /* output */
|
||||
size_t md5len);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for SecureTransport */
|
||||
#define curlssl_init() (1)
|
||||
#define curlssl_cleanup() Curl_nop_stmt
|
||||
|
@@ -87,6 +87,9 @@ extern curl_free_callback Curl_cfree;
|
||||
extern curl_realloc_callback Curl_crealloc;
|
||||
extern curl_strdup_callback Curl_cstrdup;
|
||||
extern curl_calloc_callback Curl_ccalloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
extern curl_wcsdup_callback Curl_cwcsdup;
|
||||
#endif
|
||||
|
||||
#ifndef CURLDEBUG
|
||||
|
||||
@@ -110,6 +113,20 @@ extern curl_calloc_callback Curl_ccalloc;
|
||||
#undef free
|
||||
#define free(ptr) Curl_cfree(ptr)
|
||||
|
||||
#ifdef WIN32
|
||||
# ifdef UNICODE
|
||||
# undef wcsdup
|
||||
# define wcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# undef _wcsdup
|
||||
# define _wcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) Curl_cwcsdup(ptr)
|
||||
# else
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) Curl_cstrdup(ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* CURLDEBUG */
|
||||
|
||||
#else /* CURLX_NO_MEMORY_CALLBACKS */
|
||||
|
@@ -1,61 +0,0 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_rand.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"
|
||||
|
||||
/* Private pseudo-random number seed. Unsigned integer >= 32bit. Threads
|
||||
mutual exclusion is not implemented to acess it since we do not require
|
||||
high quality random numbers (only used in form boudary generation). */
|
||||
|
||||
static unsigned int randseed;
|
||||
|
||||
/* Pseudo-random number support. */
|
||||
|
||||
unsigned int Curl_rand(void)
|
||||
{
|
||||
unsigned int r;
|
||||
/* Return an unsigned 32-bit pseudo-random number. */
|
||||
r = randseed = randseed * 1103515245 + 12345;
|
||||
return (r << 16) | ((r >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
void Curl_srand(void)
|
||||
{
|
||||
/* Randomize pseudo-random number sequence. */
|
||||
|
||||
randseed = (unsigned int) time(NULL);
|
||||
Curl_rand();
|
||||
Curl_rand();
|
||||
Curl_rand();
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@
|
||||
|
||||
#include "curl_base64.h"
|
||||
#include "curl_md5.h"
|
||||
#include "curl_rand.h"
|
||||
#include "sslgen.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_ntlm_msgs.h"
|
||||
#include "curl_sasl.h"
|
||||
@@ -314,7 +314,7 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
|
||||
/* Generate 64 bits of random data */
|
||||
for(i = 0; i < 8; i++)
|
||||
cnonce[i] = table16[Curl_rand()%16];
|
||||
cnonce[i] = table16[Curl_rand(data)%16];
|
||||
|
||||
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
|
@@ -270,6 +270,9 @@
|
||||
# endif
|
||||
# endif
|
||||
# include <tchar.h>
|
||||
# ifdef UNICODE
|
||||
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -617,7 +620,7 @@ int netware_init(void);
|
||||
#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \
|
||||
defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \
|
||||
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_DARWINSSL)
|
||||
defined(USE_DARWINSSL) || defined(USE_GSKIT)
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
|
170
lib/dotdot.c
Normal file
170
lib/dotdot.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, 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_setup.h"
|
||||
|
||||
#include "dotdot.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* "Remove Dot Segments"
|
||||
* http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
*/
|
||||
|
||||
/*
|
||||
* Curl_dedotdotify()
|
||||
*
|
||||
* This function gets a zero-terminated path with dot and dotdot sequences
|
||||
* passed in and strips them off according to the rules in RFC 3986 section
|
||||
* 5.2.4.
|
||||
*
|
||||
* The function handles a query part ('?' + stuff) appended but it expects
|
||||
* that fragments ('#' + stuff) have already been cut off.
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* an allocated dedotdotified output string
|
||||
*/
|
||||
char *Curl_dedotdotify(char *input)
|
||||
{
|
||||
size_t inlen = strlen(input);
|
||||
char *clone;
|
||||
size_t clen = inlen; /* the length of the cloned input */
|
||||
char *out = malloc(inlen+1);
|
||||
char *outptr;
|
||||
char *orgclone;
|
||||
char *queryp;
|
||||
if(!out)
|
||||
return NULL; /* out of memory */
|
||||
|
||||
/* get a cloned copy of the input */
|
||||
clone = strdup(input);
|
||||
if(!clone) {
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
orgclone = clone;
|
||||
outptr = out;
|
||||
|
||||
/*
|
||||
* To handle query-parts properly, we must find it and remove it during the
|
||||
* dotdot-operation and then append it again at the end to the output
|
||||
* string.
|
||||
*/
|
||||
queryp = strchr(clone, '?');
|
||||
if(queryp)
|
||||
*queryp = 0;
|
||||
|
||||
do {
|
||||
|
||||
/* A. If the input buffer begins with a prefix of "../" or "./", then
|
||||
remove that prefix from the input buffer; otherwise, */
|
||||
|
||||
if(!strncmp("./", clone, 2)) {
|
||||
clone+=2;
|
||||
clen-=2;
|
||||
}
|
||||
else if(!strncmp("../", clone, 3)) {
|
||||
clone+=3;
|
||||
clen-=3;
|
||||
}
|
||||
|
||||
/* B. if the input buffer begins with a prefix of "/./" or "/.", where
|
||||
"." is a complete path segment, then replace that prefix with "/" in
|
||||
the input buffer; otherwise, */
|
||||
else if(!strncmp("/./", clone, 3)) {
|
||||
clone+=2;
|
||||
clen-=2;
|
||||
}
|
||||
else if(!strcmp("/.", clone)) {
|
||||
clone[1]='/';
|
||||
clone++;
|
||||
clen-=1;
|
||||
}
|
||||
|
||||
/* C. if the input buffer begins with a prefix of "/../" or "/..", where
|
||||
".." is a complete path segment, then replace that prefix with "/" in
|
||||
the input buffer and remove the last segment and its preceding "/" (if
|
||||
any) from the output buffer; otherwise, */
|
||||
|
||||
else if(!strncmp("/../", clone, 4)) {
|
||||
clone+=3;
|
||||
clen-=3;
|
||||
/* remove the last segment from the output buffer */
|
||||
while(outptr > out) {
|
||||
outptr--;
|
||||
if(*outptr == '/')
|
||||
break;
|
||||
}
|
||||
*outptr = 0; /* zero-terminate where it stops */
|
||||
}
|
||||
else if(!strcmp("/..", clone)) {
|
||||
clone[2]='/';
|
||||
clone+=2;
|
||||
clen-=2;
|
||||
/* remove the last segment from the output buffer */
|
||||
while(outptr > out) {
|
||||
outptr--;
|
||||
if(*outptr == '/')
|
||||
break;
|
||||
}
|
||||
*outptr = 0; /* zero-terminate where it stops */
|
||||
}
|
||||
|
||||
/* D. if the input buffer consists only of "." or "..", then remove
|
||||
that from the input buffer; otherwise, */
|
||||
|
||||
else if(!strcmp(".", clone) || !strcmp("..", clone)) {
|
||||
*clone=0;
|
||||
}
|
||||
|
||||
else {
|
||||
/* E. move the first path segment in the input buffer to the end of
|
||||
the output buffer, including the initial "/" character (if any) and
|
||||
any subsequent characters up to, but not including, the next "/"
|
||||
character or the end of the input buffer. */
|
||||
|
||||
do {
|
||||
*outptr++ = *clone++;
|
||||
clen--;
|
||||
} while(*clone && (*clone != '/'));
|
||||
*outptr = 0;
|
||||
}
|
||||
|
||||
} while(*clone);
|
||||
|
||||
if(queryp) {
|
||||
size_t qlen;
|
||||
/* There was a query part, append that to the output. The 'clone' string
|
||||
may now have been altered so we copy from the original input string
|
||||
from the correct index. */
|
||||
size_t oindex = queryp - orgclone;
|
||||
qlen = strlen(&input[oindex]);
|
||||
memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */
|
||||
}
|
||||
|
||||
free(orgclone);
|
||||
return out;
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
#ifndef HEADER_CURL_RAND_H
|
||||
#define HEADER_CURL_RAND_H
|
||||
#ifndef HEADER_CURL_DOTDOT_H
|
||||
#define HEADER_CURL_DOTDOT_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -21,9 +21,5 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void Curl_srand(void);
|
||||
|
||||
unsigned int Curl_rand(void);
|
||||
|
||||
#endif /* HEADER_CURL_RAND_H */
|
||||
char *Curl_dedotdotify(char *input);
|
||||
#endif
|
93
lib/easy.c
93
lib/easy.c
@@ -50,6 +50,11 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
|
||||
#define SIGPIPE_IGNORE 1
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "strequal.h"
|
||||
#include "urldata.h"
|
||||
#include <curl/curl.h>
|
||||
@@ -69,7 +74,6 @@
|
||||
#include "connect.h" /* for Curl_getconnectinfo */
|
||||
#include "slist.h"
|
||||
#include "amigaos.h"
|
||||
#include "curl_rand.h"
|
||||
#include "non-ascii.h"
|
||||
#include "warnless.h"
|
||||
#include "conncache.h"
|
||||
@@ -81,6 +85,56 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifdef SIGPIPE_IGNORE
|
||||
struct sigpipe_ignore {
|
||||
struct sigaction old_pipe_act;
|
||||
bool no_signal;
|
||||
};
|
||||
|
||||
#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x
|
||||
|
||||
/*
|
||||
* sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl
|
||||
* internals, and then sigpipe_restore() will restore the situation when we
|
||||
* return from libcurl again.
|
||||
*/
|
||||
static void sigpipe_ignore(struct SessionHandle *data,
|
||||
struct sigpipe_ignore *ig)
|
||||
{
|
||||
/* get a local copy of no_signal because the SessionHandle might not be
|
||||
around when we restore */
|
||||
ig->no_signal = data->set.no_signal;
|
||||
if(!data->set.no_signal) {
|
||||
struct sigaction action;
|
||||
/* first, extract the existing situation */
|
||||
memset(&ig->old_pipe_act, 0, sizeof(struct sigaction));
|
||||
sigaction(SIGPIPE, NULL, &ig->old_pipe_act);
|
||||
action = ig->old_pipe_act;
|
||||
/* ignore this signal */
|
||||
action.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &action, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sigpipe_restore() puts back the outside world's opinion of signal handler
|
||||
* and SIGPIPE handling. It MUST only be called after a corresponding
|
||||
* sigpipe_ignore() was used.
|
||||
*/
|
||||
static void sigpipe_restore(struct sigpipe_ignore *ig)
|
||||
{
|
||||
if(!ig->no_signal)
|
||||
/* restore the outside state */
|
||||
sigaction(SIGPIPE, &ig->old_pipe_act, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
/* for systems without sigaction */
|
||||
#define sigpipe_ignore(x,y) Curl_nop_stmt
|
||||
#define sigpipe_restore(x) Curl_nop_stmt
|
||||
#define SIGPIPE_VARIABLE(x)
|
||||
#endif
|
||||
|
||||
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
|
||||
of win32_init() */
|
||||
static void win32_cleanup(void)
|
||||
@@ -198,6 +252,9 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
|
||||
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
|
||||
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
* Symbian OS doesn't support initialization to code in writeable static data.
|
||||
@@ -229,6 +286,9 @@ CURLcode curl_global_init(long flags)
|
||||
Curl_crealloc = (curl_realloc_callback)realloc;
|
||||
Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||
Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
|
||||
#endif
|
||||
|
||||
if(flags & CURL_GLOBAL_SSL)
|
||||
if(!Curl_ssl_init()) {
|
||||
@@ -276,10 +336,6 @@ CURLcode curl_global_init(long flags)
|
||||
|
||||
init_flags = flags;
|
||||
|
||||
/* Preset pseudo-random number sequence. */
|
||||
|
||||
Curl_srand();
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -423,6 +479,7 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
int without_fds = 0; /* count number of consecutive returns from
|
||||
curl_multi_wait() without any filedescriptors */
|
||||
struct timeval before;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!easy)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
@@ -455,6 +512,8 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
|
||||
/* assign this after curl_multi_add_handle() since that function checks for
|
||||
it and rejects this handle otherwise */
|
||||
data->multi = multi;
|
||||
@@ -480,9 +539,7 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
if(curlx_tvdiff(after, before) <= 10) {
|
||||
without_fds++;
|
||||
if(without_fds > 2) {
|
||||
int sleep_ms = without_fds * 50;
|
||||
if(sleep_ms > 1000)
|
||||
sleep_ms = 1000;
|
||||
int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000;
|
||||
Curl_wait_ms(sleep_ms);
|
||||
}
|
||||
}
|
||||
@@ -511,6 +568,8 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
a failure here, room for future improvement! */
|
||||
(void)curl_multi_remove_handle(multi, easy);
|
||||
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
/* The multi handle is kept alive, owned by the easy handle */
|
||||
return code;
|
||||
}
|
||||
@@ -522,11 +581,14 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
void curl_easy_cleanup(CURL *curl)
|
||||
{
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
Curl_close(data);
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -554,12 +616,16 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
|
||||
{
|
||||
va_list arg;
|
||||
void *paramp;
|
||||
CURLcode ret;
|
||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||
|
||||
va_start(arg, info);
|
||||
paramp = va_arg(arg, void *);
|
||||
|
||||
return Curl_getinfo(data, info, paramp);
|
||||
ret = Curl_getinfo(data, info, paramp);
|
||||
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -746,7 +812,7 @@ CURLcode curl_easy_pause(CURL *curl, int action)
|
||||
do {
|
||||
chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
|
||||
|
||||
result = Curl_client_write(data->state.current_conn,
|
||||
result = Curl_client_write(data->easy_conn,
|
||||
temptype, tempwrite, chunklen);
|
||||
if(result)
|
||||
/* failures abort the loop at once */
|
||||
@@ -788,6 +854,13 @@ CURLcode curl_easy_pause(CURL *curl, int action)
|
||||
free(freewrite); /* this is unconditionally no longer used */
|
||||
}
|
||||
|
||||
/* if there's no error and we're not pausing both directions, we want
|
||||
to have this handle checked soon */
|
||||
if(!result &&
|
||||
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
|
||||
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
|
||||
Curl_expire(data, 1); /* get this handle going again */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
145
lib/formdata.c
145
lib/formdata.c
@@ -24,9 +24,6 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
/* Length of the random boundary string. */
|
||||
#define BOUNDARY_LENGTH 40
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
|
||||
|
||||
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
|
||||
@@ -35,7 +32,7 @@
|
||||
|
||||
#include "urldata.h" /* for struct SessionHandle */
|
||||
#include "formdata.h"
|
||||
#include "curl_rand.h"
|
||||
#include "sslgen.h"
|
||||
#include "strequal.h"
|
||||
#include "curl_memory.h"
|
||||
#include "sendf.h"
|
||||
@@ -56,7 +53,7 @@ static char *Curl_basename(char *path);
|
||||
#endif
|
||||
|
||||
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
|
||||
static char *formboundary(void);
|
||||
static char *formboundary(struct SessionHandle *data);
|
||||
|
||||
/* What kind of Content-Type to use on un-specified files with unrecognized
|
||||
extensions. */
|
||||
@@ -171,7 +168,7 @@ static FormInfo * AddFormInfo(char *value,
|
||||
* Returns some valid contenttype for filename.
|
||||
*
|
||||
***************************************************************************/
|
||||
static const char * ContentTypeForFilename (const char *filename,
|
||||
static const char *ContentTypeForFilename(const char *filename,
|
||||
const char *prevtype)
|
||||
{
|
||||
const char *contenttype = NULL;
|
||||
@@ -181,7 +178,7 @@ static const char * ContentTypeForFilename (const char *filename,
|
||||
* extensions and pick the first we match!
|
||||
*/
|
||||
struct ContentType {
|
||||
char extension[6];
|
||||
const char *extension;
|
||||
const char *type;
|
||||
};
|
||||
static const struct ContentType ctts[]={
|
||||
@@ -429,7 +426,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
|
||||
/* Get contents from a given file name */
|
||||
case CURLFORM_FILECONTENT:
|
||||
if(current_form->flags != 0)
|
||||
if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
|
||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||
else {
|
||||
const char *filename = array_state?
|
||||
@@ -670,9 +667,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
||||
if(((form->flags & HTTPPOST_FILENAME) ||
|
||||
(form->flags & HTTPPOST_BUFFER)) &&
|
||||
!form->contenttype ) {
|
||||
char *f = form->flags & HTTPPOST_BUFFER?
|
||||
form->showfilename : form->value;
|
||||
|
||||
/* our contenttype is missing */
|
||||
form->contenttype
|
||||
= strdup(ContentTypeForFilename(form->value, prevtype));
|
||||
form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
|
||||
if(!form->contenttype) {
|
||||
return_value = CURL_FORMADD_MEMORY;
|
||||
break;
|
||||
@@ -777,6 +776,70 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __VMS
|
||||
#include <fabdef.h>
|
||||
/*
|
||||
* get_vms_file_size does what it takes to get the real size of the file
|
||||
*
|
||||
* For fixed files, find out the size of the EOF block and adjust.
|
||||
*
|
||||
* For all others, have to read the entire file in, discarding the contents.
|
||||
* Most posted text files will be small, and binary files like zlib archives
|
||||
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
|
||||
*
|
||||
*/
|
||||
curl_off_t VmsRealFileSize(const char * name,
|
||||
const struct_stat * stat_buf)
|
||||
{
|
||||
char buffer[8192];
|
||||
curl_off_t count;
|
||||
int ret_stat;
|
||||
FILE * file;
|
||||
|
||||
file = fopen(name, "r");
|
||||
if(file == NULL)
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
ret_stat = 1;
|
||||
while(ret_stat > 0) {
|
||||
ret_stat = fread(buffer, 1, sizeof(buffer), file);
|
||||
if(ret_stat != 0)
|
||||
count += ret_stat;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* VmsSpecialSize checks to see if the stat st_size can be trusted and
|
||||
* if not to call a routine to get the correct size.
|
||||
*
|
||||
*/
|
||||
static curl_off_t VmsSpecialSize(const char * name,
|
||||
const struct_stat * stat_buf)
|
||||
{
|
||||
switch(stat_buf->st_fab_rfm) {
|
||||
case FAB$C_VAR:
|
||||
case FAB$C_VFC:
|
||||
return VmsRealFileSize(name, stat_buf);
|
||||
break;
|
||||
default:
|
||||
return stat_buf->st_size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __VMS
|
||||
#define filesize(name, stat_data) (stat_data.st_size)
|
||||
#else
|
||||
/* Getting the expected file size needs help on VMS */
|
||||
#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AddFormData() adds a chunk of data to the FormData linked list.
|
||||
*
|
||||
@@ -832,7 +895,7 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
if(!strequal("-", newform->line)) {
|
||||
struct_stat file;
|
||||
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
|
||||
*size += file.st_size;
|
||||
*size += filesize(newform->line, file);
|
||||
else
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
@@ -1101,7 +1164,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
if(!post)
|
||||
return result; /* no input => no output! */
|
||||
|
||||
boundary = formboundary();
|
||||
boundary = formboundary(data);
|
||||
if(!boundary)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -1157,7 +1220,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
the magic to include several files with the same field name */
|
||||
|
||||
Curl_safefree(fileboundary);
|
||||
fileboundary = formboundary();
|
||||
fileboundary = formboundary(data);
|
||||
if(!fileboundary) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
@@ -1343,6 +1406,36 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __VMS
|
||||
# define fopen_read fopen
|
||||
#else
|
||||
/*
|
||||
* vmsfopenread
|
||||
*
|
||||
* For upload to work as expected on VMS, different optional
|
||||
* parameters must be added to the fopen command based on
|
||||
* record format of the file.
|
||||
*
|
||||
*/
|
||||
# define fopen_read vmsfopenread
|
||||
static FILE * vmsfopenread(const char *file, const char *mode) {
|
||||
struct_stat statbuf;
|
||||
int result;
|
||||
|
||||
result = stat(file, &statbuf);
|
||||
|
||||
switch (statbuf.st_fab_rfm) {
|
||||
case FAB$C_VAR:
|
||||
case FAB$C_VFC:
|
||||
case FAB$C_STMCR:
|
||||
return fopen(file, "r");
|
||||
break;
|
||||
default:
|
||||
return fopen(file, "r", "rfm=stmlf", "ctx=stm");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* readfromfile()
|
||||
*
|
||||
@@ -1365,7 +1458,7 @@ static size_t readfromfile(struct Form *form, char *buffer,
|
||||
else {
|
||||
if(!form->fp) {
|
||||
/* this file hasn't yet been opened */
|
||||
form->fp = fopen(form->data->line, "rb"); /* b is for binary */
|
||||
form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
|
||||
if(!form->fp)
|
||||
return (size_t)-1; /* failure */
|
||||
}
|
||||
@@ -1464,28 +1557,12 @@ char *Curl_formpostheader(void *formp, size_t *len)
|
||||
* formboundary() creates a suitable boundary string and returns an allocated
|
||||
* one.
|
||||
*/
|
||||
static char *formboundary(void)
|
||||
static char *formboundary(struct SessionHandle *data)
|
||||
{
|
||||
char *retstring;
|
||||
size_t i;
|
||||
|
||||
static const char table16[]="0123456789abcdef";
|
||||
|
||||
retstring = malloc(BOUNDARY_LENGTH+1);
|
||||
|
||||
if(!retstring)
|
||||
return NULL; /* failed */
|
||||
|
||||
strcpy(retstring, "----------------------------");
|
||||
|
||||
for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
|
||||
retstring[i] = table16[Curl_rand()%16];
|
||||
|
||||
/* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
|
||||
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
|
||||
combinations */
|
||||
retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
|
||||
|
||||
return retstring;
|
||||
return aprintf("------------------------%08x%08x",
|
||||
Curl_rand(data), Curl_rand(data));
|
||||
}
|
||||
|
||||
#else /* CURL_DISABLE_HTTP */
|
||||
|
151
lib/ftp.c
151
lib/ftp.c
@@ -123,8 +123,8 @@ static void ftp_pasv_verbose(struct connectdata *conn,
|
||||
char *newhost, /* ascii version */
|
||||
int port);
|
||||
#endif
|
||||
static CURLcode ftp_state_post_rest(struct connectdata *conn);
|
||||
static CURLcode ftp_state_post_cwd(struct connectdata *conn);
|
||||
static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
|
||||
static CURLcode ftp_state_mdtm(struct connectdata *conn);
|
||||
static CURLcode ftp_state_quote(struct connectdata *conn,
|
||||
bool init, ftpstate instate);
|
||||
static CURLcode ftp_nb_type(struct connectdata *conn,
|
||||
@@ -136,7 +136,7 @@ static CURLcode ftp_done(struct connectdata *conn,
|
||||
CURLcode, bool premature);
|
||||
static CURLcode ftp_connect(struct connectdata *conn, bool *done);
|
||||
static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
|
||||
static CURLcode ftp_do_more(struct connectdata *conn, bool *completed);
|
||||
static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
|
||||
static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
|
||||
static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks);
|
||||
@@ -151,8 +151,7 @@ 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);
|
||||
static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
|
||||
|
||||
static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
struct pingpong *pp,
|
||||
@@ -828,7 +827,7 @@ static void _state(struct connectdata *conn,
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(ftpc->state != newstate)
|
||||
infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
|
||||
ftpc, lineno, names[ftpc->state], names[newstate]);
|
||||
(void *)ftpc, lineno, names[ftpc->state], names[newstate]);
|
||||
#endif
|
||||
ftpc->state = newstate;
|
||||
}
|
||||
@@ -851,7 +850,7 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
|
||||
CURLcode result;
|
||||
|
||||
/* send PWD to discover our entry point */
|
||||
PPSENDF(&conn->proto.ftpc.pp, "PWD", NULL);
|
||||
PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
|
||||
state(conn, FTP_PWD);
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -915,7 +914,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
|
||||
|
||||
if(ftpc->cwddone)
|
||||
/* already done and fine */
|
||||
result = ftp_state_post_cwd(conn);
|
||||
result = ftp_state_mdtm(conn);
|
||||
else {
|
||||
ftpc->count2 = 0; /* count2 counts failed CWDs */
|
||||
|
||||
@@ -943,7 +942,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
|
||||
}
|
||||
else {
|
||||
/* No CWD necessary */
|
||||
result = ftp_state_post_cwd(conn);
|
||||
result = ftp_state_mdtm(conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1373,10 +1372,14 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* REST is the last command in the chain of commands when a "head"-like
|
||||
request is made. Thus, if an actual transfer is to be made this is where
|
||||
we take off for real. */
|
||||
static CURLcode ftp_state_post_rest(struct connectdata *conn)
|
||||
/*
|
||||
* ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
|
||||
*
|
||||
* REST is the last command in the chain of commands when a "head"-like
|
||||
* request is made. Thus, if an actual transfer is to be made this is where we
|
||||
* take off for real.
|
||||
*/
|
||||
static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
@@ -1419,7 +1422,7 @@ static CURLcode ftp_state_post_rest(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_size(struct connectdata *conn)
|
||||
static CURLcode ftp_state_rest(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
@@ -1435,12 +1438,12 @@ static CURLcode ftp_state_post_size(struct connectdata *conn)
|
||||
state(conn, FTP_REST);
|
||||
}
|
||||
else
|
||||
result = ftp_state_post_rest(conn);
|
||||
result = ftp_state_prepare_transfer(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_type(struct connectdata *conn)
|
||||
static CURLcode ftp_state_size(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
@@ -1455,12 +1458,12 @@ static CURLcode ftp_state_post_type(struct connectdata *conn)
|
||||
state(conn, FTP_SIZE);
|
||||
}
|
||||
else
|
||||
result = ftp_state_post_size(conn);
|
||||
result = ftp_state_rest(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_listtype(struct connectdata *conn)
|
||||
static CURLcode ftp_state_list(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@@ -1529,7 +1532,7 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_retrtype(struct connectdata *conn)
|
||||
static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
@@ -1540,7 +1543,7 @@ static CURLcode ftp_state_post_retrtype(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_stortype(struct connectdata *conn)
|
||||
static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
@@ -1551,7 +1554,7 @@ static CURLcode ftp_state_post_stortype(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_mdtm(struct connectdata *conn)
|
||||
static CURLcode ftp_state_type(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
@@ -1577,14 +1580,14 @@ static CURLcode ftp_state_post_mdtm(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
result = ftp_state_post_type(conn);
|
||||
result = ftp_state_size(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This is called after the CWD commands have been done in the beginning of
|
||||
the DO phase */
|
||||
static CURLcode ftp_state_post_cwd(struct connectdata *conn)
|
||||
static CURLcode ftp_state_mdtm(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@@ -1600,7 +1603,7 @@ static CURLcode ftp_state_post_cwd(struct connectdata *conn)
|
||||
state(conn, FTP_MDTM);
|
||||
}
|
||||
else
|
||||
result = ftp_state_post_mdtm(conn);
|
||||
result = ftp_state_type(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1775,7 +1778,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
|
||||
else {
|
||||
if(ftpc->known_filesize != -1) {
|
||||
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
|
||||
result = ftp_state_post_retr_size(conn, ftpc->known_filesize);
|
||||
result = ftp_state_retr(conn, ftpc->known_filesize);
|
||||
}
|
||||
else {
|
||||
PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
|
||||
@@ -1799,15 +1802,15 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
|
||||
static CURLcode ftp_epsv_disable(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
infof(conn->data, "got positive EPSV response, but can't connect. "
|
||||
"Disabling EPSV\n");
|
||||
infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
|
||||
/* disable it for next transfer */
|
||||
conn->bits.ftp_use_epsv = FALSE;
|
||||
conn->data->state.errorbuf = FALSE; /* allow error message to get
|
||||
rewritten */
|
||||
PPSENDF(&conn->proto.ftpc.pp, "PASV", NULL);
|
||||
PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
|
||||
conn->proto.ftpc.count1++;
|
||||
/* remain in the FTP_PASV state */
|
||||
/* remain in/go to the FTP_PASV state */
|
||||
state(conn, FTP_PASV);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1936,15 +1939,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
}
|
||||
else if(ftpc->count1 == 0) {
|
||||
/* EPSV failed, move on to PASV */
|
||||
|
||||
/* disable it for next transfer */
|
||||
conn->bits.ftp_use_epsv = FALSE;
|
||||
infof(data, "disabling EPSV usage\n");
|
||||
|
||||
PPSENDF(&ftpc->pp, "PASV", NULL);
|
||||
ftpc->count1++;
|
||||
/* remain in the FTP_PASV state */
|
||||
return result;
|
||||
return ftp_epsv_disable(conn);
|
||||
}
|
||||
else {
|
||||
failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
|
||||
@@ -2021,14 +2016,17 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport,
|
||||
SECONDARYSOCKET, conn);
|
||||
connected = TRUE;
|
||||
break;
|
||||
case CURLPROXY_SOCKS4:
|
||||
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
|
||||
SECONDARYSOCKET, conn, FALSE);
|
||||
connected = TRUE;
|
||||
break;
|
||||
case CURLPROXY_SOCKS4A:
|
||||
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
|
||||
SECONDARYSOCKET, conn, TRUE);
|
||||
connected = TRUE;
|
||||
break;
|
||||
case CURLPROXY_HTTP:
|
||||
case CURLPROXY_HTTP_1_0:
|
||||
@@ -2080,8 +2078,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
|
||||
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
|
||||
conn->bits.do_more = TRUE;
|
||||
state(conn, FTP_STOP); /* this phase is completed */
|
||||
|
||||
@@ -2221,7 +2218,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
}
|
||||
|
||||
if(!result)
|
||||
result = ftp_state_post_mdtm(conn);
|
||||
result = ftp_state_type(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2245,18 +2242,18 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn,
|
||||
ftpcode);
|
||||
|
||||
if(instate == FTP_TYPE)
|
||||
result = ftp_state_post_type(conn);
|
||||
result = ftp_state_size(conn);
|
||||
else if(instate == FTP_LIST_TYPE)
|
||||
result = ftp_state_post_listtype(conn);
|
||||
result = ftp_state_list(conn);
|
||||
else if(instate == FTP_RETR_TYPE)
|
||||
result = ftp_state_post_retrtype(conn);
|
||||
result = ftp_state_retr_prequote(conn);
|
||||
else if(instate == FTP_STOR_TYPE)
|
||||
result = ftp_state_post_stortype(conn);
|
||||
result = ftp_state_stor_prequote(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_post_retr_size(struct connectdata *conn,
|
||||
static CURLcode ftp_state_retr(struct connectdata *conn,
|
||||
curl_off_t filesize)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -2361,11 +2358,11 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
Curl_pgrsSetDownloadSize(data, filesize);
|
||||
result = ftp_state_post_size(conn);
|
||||
result = ftp_state_rest(conn);
|
||||
}
|
||||
else if(instate == FTP_RETR_SIZE) {
|
||||
Curl_pgrsSetDownloadSize(data, filesize);
|
||||
result = ftp_state_post_retr_size(conn, filesize);
|
||||
result = ftp_state_retr(conn, filesize);
|
||||
}
|
||||
else if(instate == FTP_STOR_SIZE) {
|
||||
data->state.resume_from = filesize;
|
||||
@@ -2393,7 +2390,7 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
result = ftp_state_post_rest(conn);
|
||||
result = ftp_state_prepare_transfer(conn);
|
||||
break;
|
||||
|
||||
case FTP_RETR_REST:
|
||||
@@ -2834,7 +2831,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
if(data->set.ftp_ccc) {
|
||||
/* CCC - Clear Command Channel
|
||||
*/
|
||||
PPSENDF(&ftpc->pp, "CCC", NULL);
|
||||
PPSENDF(&ftpc->pp, "%s", "CCC");
|
||||
state(conn, FTP_CCC);
|
||||
}
|
||||
else {
|
||||
@@ -2921,7 +2918,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
|
||||
if(!ftpc->server_os && dir[0] != '/') {
|
||||
|
||||
result = Curl_pp_sendf(&ftpc->pp, "SYST", NULL);
|
||||
result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
|
||||
if(result != CURLE_OK) {
|
||||
free(dir);
|
||||
return result;
|
||||
@@ -2974,7 +2971,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
|
||||
if(strequal(os, "OS/400")) {
|
||||
/* Force OS400 name format 1. */
|
||||
result = Curl_pp_sendf(&ftpc->pp, "SITE NAMEFMT 1", NULL);
|
||||
result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
|
||||
if(result != CURLE_OK) {
|
||||
free(os);
|
||||
return result;
|
||||
@@ -3052,7 +3049,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
|
||||
}
|
||||
else {
|
||||
result = ftp_state_post_cwd(conn);
|
||||
result = ftp_state_mdtm(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -3216,8 +3213,8 @@ static CURLcode ftp_init(struct connectdata *conn)
|
||||
* the connection phase.
|
||||
*
|
||||
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
||||
* phase is done when this function returns, or FALSE is not. When called as
|
||||
* a part of the easy interface, it will always be TRUE.
|
||||
* phase is done when this function returns, or FALSE if not.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_connect(struct connectdata *conn,
|
||||
bool *done) /* see description above */
|
||||
@@ -3383,7 +3380,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
|
||||
if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
|
||||
/* partial download completed */
|
||||
result = Curl_pp_sendf(pp, "ABOR");
|
||||
result = Curl_pp_sendf(pp, "%s", "ABOR");
|
||||
if(result) {
|
||||
failf(data, "Failure sending ABOR command: %s",
|
||||
curl_easy_strerror(result));
|
||||
@@ -3677,20 +3674,23 @@ static CURLcode ftp_range(struct connectdata *conn)
|
||||
*
|
||||
* This function shall be called when the second FTP (data) connection is
|
||||
* connected.
|
||||
*
|
||||
* 'complete' can return 0 for incomplete, 1 for done and -1 for go back
|
||||
* (which basically is only for when PASV is being sent to retry a failed
|
||||
* EPSV).
|
||||
*/
|
||||
|
||||
static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
{
|
||||
struct SessionHandle *data=conn->data;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
CURLcode result = CURLE_OK;
|
||||
bool connected = FALSE;
|
||||
bool complete = FALSE;
|
||||
|
||||
/* the ftp struct is inited in ftp_connect() */
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
|
||||
*complete = FALSE;
|
||||
|
||||
/* if the second connection isn't done yet, wait for it */
|
||||
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
||||
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
|
||||
@@ -3707,14 +3707,22 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
if(connected) {
|
||||
DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
|
||||
}
|
||||
else
|
||||
else {
|
||||
if(result && (ftpc->count1 == 0)) {
|
||||
*completep = -1; /* go back to DOING please */
|
||||
/* this is a EPSV connect failing, try PASV instead */
|
||||
return ftp_epsv_disable(conn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(ftpc->state) {
|
||||
/* already in a state so skip the intial commands.
|
||||
They are only done to kickstart the do_more state */
|
||||
result = ftp_multi_statemach(conn, complete);
|
||||
result = ftp_multi_statemach(conn, &complete);
|
||||
|
||||
*completep = (int)complete;
|
||||
|
||||
/* if we got an error or if we don't wait for a data connection return
|
||||
immediately */
|
||||
@@ -3725,7 +3733,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
/* if we reach the end of the FTP state machine here, *complete will be
|
||||
TRUE but so is ftpc->wait_data_conn, which says we need to wait for
|
||||
the data connection and therefore we're not actually complete */
|
||||
*complete = FALSE;
|
||||
*completep = 0;
|
||||
}
|
||||
|
||||
if(ftp->transfer <= FTPTRANSFER_INFO) {
|
||||
@@ -3748,6 +3756,9 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
*completep = 1; /* this state is now complete when the server has
|
||||
connected back to us */
|
||||
}
|
||||
}
|
||||
else if(data->set.upload) {
|
||||
@@ -3755,7 +3766,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = ftp_multi_statemach(conn, complete);
|
||||
result = ftp_multi_statemach(conn, &complete);
|
||||
*completep = (int)complete;
|
||||
}
|
||||
else {
|
||||
/* download */
|
||||
@@ -3783,7 +3795,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ftp_multi_statemach(conn, complete);
|
||||
result = ftp_multi_statemach(conn, &complete);
|
||||
*completep = (int)complete;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -3795,7 +3808,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete)
|
||||
|
||||
if(!ftpc->wait_data_conn) {
|
||||
/* no waiting for the data connection so this is now complete */
|
||||
*complete = TRUE;
|
||||
*completep = 1;
|
||||
DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
|
||||
}
|
||||
|
||||
@@ -3838,7 +3851,9 @@ CURLcode ftp_perform(struct connectdata *conn,
|
||||
/* run the state-machine */
|
||||
result = ftp_multi_statemach(conn, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
|
||||
|
||||
infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
|
||||
|
||||
if(*dophase_done)
|
||||
DEBUGF(infof(conn->data, "DO phase is complete1\n"));
|
||||
@@ -4189,7 +4204,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn->proto.ftpc.ctl_valid) {
|
||||
result = Curl_pp_sendf(&conn->proto.ftpc.pp, "QUIT", NULL);
|
||||
result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
|
||||
if(result) {
|
||||
failf(conn->data, "Failure sending QUIT command: %s",
|
||||
curl_easy_strerror(result));
|
||||
@@ -4466,7 +4481,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if(connected) {
|
||||
bool completed;
|
||||
int completed;
|
||||
CURLcode result = ftp_do_more(conn, &completed);
|
||||
|
||||
if(result) {
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -53,9 +53,9 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
|
||||
pro->t_redirect = 0;
|
||||
|
||||
info->httpcode = 0;
|
||||
info->httpversion=0;
|
||||
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
||||
info->timecond=0;
|
||||
info->httpversion = 0;
|
||||
info->filetime = -1; /* -1 is an illegal time and thus means unknown */
|
||||
info->timecond = FALSE;
|
||||
|
||||
if(info->contenttype)
|
||||
free(info->contenttype);
|
||||
@@ -186,7 +186,7 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
|
||||
break;
|
||||
case CURLINFO_CONDITION_UNMET:
|
||||
/* return if the condition prevented the document to get transferred */
|
||||
*param_longp = data->info.timecond;
|
||||
*param_longp = data->info.timecond ? 1L : 0L;
|
||||
break;
|
||||
case CURLINFO_RTSP_CLIENT_CSEQ:
|
||||
*param_longp = data->state.rtsp_next_client_CSeq;
|
||||
|
906
lib/gskit.c
Normal file
906
lib/gskit.c
Normal file
@@ -0,0 +1,906 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, 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_setup.h"
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
|
||||
#include <gskssl.h>
|
||||
#include <qsoasync.h>
|
||||
|
||||
/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
|
||||
#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
|
||||
#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "gskit.h"
|
||||
#include "sslgen.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
#include "select.h"
|
||||
#include "strequal.h"
|
||||
#include "x509asn1.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"
|
||||
|
||||
|
||||
/* Supported ciphers. */
|
||||
typedef struct {
|
||||
const char * name; /* Cipher name. */
|
||||
const char * gsktoken; /* Corresponding token for GSKit String. */
|
||||
int sslver; /* SSL version. */
|
||||
} gskit_cipher;
|
||||
|
||||
static const gskit_cipher ciphertable[] = {
|
||||
{ "null-md5", "01", CURL_SSLVERSION_SSLv3 },
|
||||
{ "null-sha", "02", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-rc4-md5", "03", CURL_SSLVERSION_SSLv3 },
|
||||
{ "rc4-md5", "04", CURL_SSLVERSION_SSLv3 },
|
||||
{ "rc4-sha", "05", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-rc2-cbc-md5", "06", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-des-cbc-sha", "09", CURL_SSLVERSION_SSLv3 },
|
||||
{ "des-cbc3-sha", "0A", CURL_SSLVERSION_SSLv3 },
|
||||
{ "aes128-sha", "2F", CURL_SSLVERSION_TLSv1 },
|
||||
{ "aes256-sha", "35", CURL_SSLVERSION_TLSv1 },
|
||||
{ "rc4-md5", "1", CURL_SSLVERSION_SSLv2 },
|
||||
{ "exp-rc4-md5", "2", CURL_SSLVERSION_SSLv2 },
|
||||
{ "rc2-md5", "3", CURL_SSLVERSION_SSLv2 },
|
||||
{ "exp-rc2-md5", "4", CURL_SSLVERSION_SSLv2 },
|
||||
{ "des-cbc-md5", "6", CURL_SSLVERSION_SSLv2 },
|
||||
{ "des-cbc3-md5", "7", CURL_SSLVERSION_SSLv2 },
|
||||
{ (const char *) NULL, (const char *) NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
static bool is_separator(char c)
|
||||
{
|
||||
/* Return whether character is a cipher list separator. */
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case ':':
|
||||
case ',':
|
||||
case ';':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode gskit_status(struct SessionHandle * data, int rc,
|
||||
const char * procname, CURLcode defcode)
|
||||
{
|
||||
CURLcode cc;
|
||||
|
||||
/* Process GSKit status and map it to a CURLcode. */
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
|
||||
return CURLE_OK;
|
||||
case GSK_KEYRING_OPEN_ERROR:
|
||||
case GSK_OS400_ERROR_NO_ACCESS:
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
case GSK_INSUFFICIENT_STORAGE:
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
case GSK_ERROR_BAD_V2_CIPHER:
|
||||
case GSK_ERROR_BAD_V3_CIPHER:
|
||||
case GSK_ERROR_NO_CIPHERS:
|
||||
return CURLE_SSL_CIPHER;
|
||||
case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
|
||||
case GSK_ERROR_CERT_VALIDATION:
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
case GSK_OS400_ERROR_TIMED_OUT:
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
case GSK_WOULD_BLOCK:
|
||||
return CURLE_AGAIN;
|
||||
case GSK_OS400_ERROR_NOT_REGISTERED:
|
||||
break;
|
||||
case GSK_ERROR_IO:
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
default:
|
||||
failf(data, "%s I/O error: %s", procname, strerror(errno));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
failf(data, "%s: %s", procname, gsk_strerror(rc));
|
||||
break;
|
||||
}
|
||||
return defcode;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_enum(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value)
|
||||
{
|
||||
int rc = gsk_attribute_set_enum(h, id, value);
|
||||
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
return CURLE_OK;
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
|
||||
break;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
}
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_buffer(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_BUF_ID id, const char * buffer)
|
||||
{
|
||||
int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
|
||||
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
return CURLE_OK;
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
|
||||
break;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
}
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_numeric(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_NUM_ID id, int value)
|
||||
{
|
||||
int rc = gsk_attribute_set_numeric_value(h, id, value);
|
||||
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
return CURLE_OK;
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
|
||||
strerror(errno));
|
||||
break;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
}
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_callback(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_CALLBACK_ID id, void * info)
|
||||
{
|
||||
int rc = gsk_attribute_set_callback(h, id, info);
|
||||
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
return CURLE_OK;
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
|
||||
break;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
}
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h)
|
||||
{
|
||||
const char * cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
char * sslv2ciphers;
|
||||
char * sslv3ciphers;
|
||||
const char * clp;
|
||||
const gskit_cipher * ctp;
|
||||
char * v2p;
|
||||
char * v3p;
|
||||
int i;
|
||||
CURLcode cc;
|
||||
|
||||
/* Compile cipher list into GSKit-compatible cipher lists. */
|
||||
|
||||
if(!cipherlist)
|
||||
return CURLE_OK;
|
||||
while(is_separator(*cipherlist)) /* Skip initial separators. */
|
||||
cipherlist++;
|
||||
if(!*cipherlist)
|
||||
return CURLE_OK;
|
||||
|
||||
/* We allocate GSKit buffers of the same size as the input string: since
|
||||
GSKit tokens are always shorter than their cipher names, allocated buffers
|
||||
will always be large enough to accomodate the result. */
|
||||
i = strlen(cipherlist) + 1;
|
||||
v2p = malloc(i);
|
||||
if(!v2p)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
v3p = malloc(i);
|
||||
if(!v3p) {
|
||||
free(v2p);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
sslv2ciphers = v2p;
|
||||
sslv3ciphers = v3p;
|
||||
|
||||
/* Process each cipher in input string. */
|
||||
for(;;) {
|
||||
for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
|
||||
cipherlist++;
|
||||
i = cipherlist - clp;
|
||||
if(!i)
|
||||
break;
|
||||
/* Search the cipher in our table. */
|
||||
for(ctp = ciphertable; ctp->name; ctp++)
|
||||
if(strnequal(ctp->name, clp, i) && !ctp->name[i])
|
||||
break;
|
||||
if(!ctp->name)
|
||||
failf(data, "Unknown cipher %.*s: ignored", i, clp);
|
||||
else {
|
||||
switch (ctp->sslver) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
strcpy(v2p, ctp->gsktoken);
|
||||
v2p += strlen(v2p);
|
||||
break;
|
||||
default:
|
||||
/* GSKit wants TLSv1 ciphers with SSLv3 ciphers. */
|
||||
strcpy(v3p, ctp->gsktoken);
|
||||
v3p += strlen(v3p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to next cipher name or end of string. */
|
||||
while(is_separator(*cipherlist))
|
||||
cipherlist++;
|
||||
}
|
||||
*v2p = '\0';
|
||||
*v3p = '\0';
|
||||
cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS, sslv2ciphers);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, sslv3ciphers);
|
||||
free(sslv2ciphers);
|
||||
free(sslv3ciphers);
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
int Curl_gskit_init(void)
|
||||
{
|
||||
/* No initialisation needed. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Curl_gskit_cleanup(void)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
|
||||
static CURLcode init_environment(struct SessionHandle * data,
|
||||
gsk_handle * envir, const char * appid,
|
||||
const char * file, const char * label,
|
||||
const char * password)
|
||||
{
|
||||
int rc;
|
||||
CURLcode c;
|
||||
gsk_handle h;
|
||||
|
||||
/* Creates the GSKit environment. */
|
||||
|
||||
rc = gsk_environment_open(&h);
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
break;
|
||||
case GSK_INSUFFICIENT_STORAGE:
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
default:
|
||||
failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION);
|
||||
if(c == CURLE_OK && appid)
|
||||
c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid);
|
||||
if(c == CURLE_OK && file)
|
||||
c = set_buffer(data, h, GSK_KEYRING_FILE, file);
|
||||
if(c == CURLE_OK && label)
|
||||
c = set_buffer(data, h, GSK_KEYRING_LABEL, label);
|
||||
if(c == CURLE_OK && password)
|
||||
c = set_buffer(data, h, GSK_KEYRING_PW, password);
|
||||
|
||||
if(c == CURLE_OK) {
|
||||
/* Locate CAs, Client certificate and key according to our settings.
|
||||
Note: this call may be blocking for some tenths of seconds. */
|
||||
c = gskit_status(data, gsk_environment_init(h),
|
||||
"gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
|
||||
if(c == CURLE_OK) {
|
||||
*envir = h;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
/* Error: rollback. */
|
||||
gsk_environment_close(&h);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static void cancel_async_handshake(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
Qso_OverlappedIO_t cstat;
|
||||
|
||||
if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
|
||||
QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
|
||||
}
|
||||
|
||||
|
||||
static void close_async_handshake(struct ssl_connect_data * connssl)
|
||||
{
|
||||
QsoDestroyIOCompletionPort(connssl->iocport);
|
||||
connssl->iocport = -1;
|
||||
}
|
||||
|
||||
|
||||
static void close_one(struct ssl_connect_data * conn,
|
||||
struct SessionHandle * data)
|
||||
{
|
||||
if(conn->handle) {
|
||||
gskit_status(data, gsk_secure_soc_close(&conn->handle),
|
||||
"gsk_secure_soc_close()", 0);
|
||||
conn->handle = (gsk_handle) NULL;
|
||||
}
|
||||
if(conn->iocport >= 0)
|
||||
close_async_handshake(conn);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t gskit_send(struct connectdata * conn, int sockindex,
|
||||
const void * mem, size_t len, CURLcode * curlcode)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
CURLcode cc;
|
||||
int written;
|
||||
|
||||
cc = gskit_status(data,
|
||||
gsk_secure_soc_write(conn->ssl[sockindex].handle,
|
||||
(char *) mem, (int) len, &written),
|
||||
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
|
||||
if(cc != CURLE_OK) {
|
||||
*curlcode = cc;
|
||||
written = -1;
|
||||
}
|
||||
return (ssize_t) written; /* number of bytes */
|
||||
}
|
||||
|
||||
|
||||
static ssize_t gskit_recv(struct connectdata * conn, int num, char * buf,
|
||||
size_t buffersize, CURLcode * curlcode)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
int buffsize;
|
||||
int nread;
|
||||
CURLcode cc;
|
||||
|
||||
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
|
||||
cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
|
||||
buf, buffsize, &nread),
|
||||
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
|
||||
if(cc != CURLE_OK) {
|
||||
*curlcode = cc;
|
||||
nread = -1;
|
||||
}
|
||||
return (ssize_t) nread;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
gsk_handle envir;
|
||||
CURLcode cc;
|
||||
int rc;
|
||||
char * keyringfile;
|
||||
char * keyringpwd;
|
||||
char * keyringlabel;
|
||||
char * v2ciphers;
|
||||
char * v3ciphers;
|
||||
char * sni;
|
||||
bool sslv2enable, sslv3enable, tlsv1enable;
|
||||
long timeout;
|
||||
Qso_OverlappedIO_t commarea;
|
||||
|
||||
/* Create SSL environment, start (preferably asynchronous) handshake. */
|
||||
|
||||
connssl->handle = (gsk_handle) NULL;
|
||||
connssl->iocport = -1;
|
||||
|
||||
/* GSKit supports two ways of specifying an SSL context: either by
|
||||
* application identifier (that should have been defined at the system
|
||||
* level) or by keyring file, password and certificate label.
|
||||
* Local certificate name (CURLOPT_SSLCERT) is used to hold either the
|
||||
* application identifier of the certificate label.
|
||||
* Key password (CURLOPT_KEYPASSWD) holds the keyring password.
|
||||
* It is not possible to have different keyrings for the CAs and the
|
||||
* local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
|
||||
* the keyring file.
|
||||
* If no key password is given and the keyring is the system keyring,
|
||||
* application identifier mode is tried first, as recommended in IBM doc.
|
||||
*/
|
||||
|
||||
keyringfile = data->set.str[STRING_SSL_CAFILE];
|
||||
keyringpwd = data->set.str[STRING_KEY_PASSWD];
|
||||
keyringlabel = data->set.str[STRING_CERT];
|
||||
envir = (gsk_handle) NULL;
|
||||
|
||||
if(keyringlabel && *keyringlabel && !keyringpwd &&
|
||||
!strcmp(keyringfile, CURL_CA_BUNDLE)) {
|
||||
/* Try application identifier mode. */
|
||||
init_environment(data, &envir, keyringlabel, (const char *) NULL,
|
||||
(const char *) NULL, (const char *) NULL);
|
||||
}
|
||||
|
||||
if(!envir) {
|
||||
/* Use keyring mode. */
|
||||
cc = init_environment(data, &envir, (const char *) NULL,
|
||||
keyringfile, keyringlabel, keyringpwd);
|
||||
if(cc != CURLE_OK)
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* Create secure session. */
|
||||
cc = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
|
||||
"gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
|
||||
gsk_environment_close(&envir);
|
||||
if(cc != CURLE_OK)
|
||||
return cc;
|
||||
|
||||
/* Determine which SSL/TLS version should be enabled. */
|
||||
sslv2enable = sslv3enable = tlsv1enable = false;
|
||||
sni = conn->host.name;
|
||||
switch (data->set.ssl.version) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
sslv2enable = true;
|
||||
sni = (char *) NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
sslv3enable = true;
|
||||
sni = (char *) NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
tlsv1enable = true;
|
||||
break;
|
||||
default: /* CURL_SSLVERSION_DEFAULT. */
|
||||
sslv3enable = true;
|
||||
tlsv1enable = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */
|
||||
if(sni) {
|
||||
rc = gsk_attribute_set_buffer(connssl->handle,
|
||||
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, 0);
|
||||
switch (rc) {
|
||||
case GSK_OK:
|
||||
case GSK_ATTRIBUTE_INVALID_ID:
|
||||
break;
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
|
||||
cc = CURLE_SSL_CONNECT_ERROR;
|
||||
break;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
|
||||
cc = CURLE_SSL_CONNECT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set session parameters. */
|
||||
if(cc == CURLE_OK) {
|
||||
/* Compute the handshake timeout. Since GSKit granularity is 1 second,
|
||||
we round up the required value. */
|
||||
timeout = Curl_timeleft(data, NULL, TRUE);
|
||||
if(timeout < 0)
|
||||
cc = CURLE_OPERATION_TIMEDOUT;
|
||||
else
|
||||
cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
|
||||
(timeout + 999) / 1000);
|
||||
}
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_ciphers(data, connssl->handle);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
|
||||
sslv2enable? GSK_PROTOCOL_SSLV2_ON:
|
||||
GSK_PROTOCOL_SSLV2_OFF);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
|
||||
sslv3enable? GSK_PROTOCOL_SSLV3_ON:
|
||||
GSK_PROTOCOL_SSLV3_OFF);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
|
||||
sslv3enable? GSK_PROTOCOL_TLSV1_ON:
|
||||
GSK_PROTOCOL_TLSV1_OFF);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
|
||||
data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
|
||||
GSK_SERVER_AUTH_PASSTHRU);
|
||||
|
||||
if(cc == CURLE_OK) {
|
||||
/* Start handshake. Try asynchronous first. */
|
||||
memset(&commarea, 0, sizeof commarea);
|
||||
connssl->iocport = QsoCreateIOCompletionPort();
|
||||
if(connssl->iocport != -1) {
|
||||
cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle,
|
||||
connssl->iocport, &commarea),
|
||||
"gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR);
|
||||
if(cc == CURLE_OK) {
|
||||
connssl->connecting_state = ssl_connect_2;
|
||||
return CURLE_OK;
|
||||
}
|
||||
else
|
||||
close_async_handshake(connssl);
|
||||
}
|
||||
else if(errno != ENOBUFS)
|
||||
cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0);
|
||||
else {
|
||||
/* No more completion port available. Use synchronous IO. */
|
||||
cc = gskit_status(data, gsk_secure_soc_init(connssl->handle),
|
||||
"gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
|
||||
if(cc == CURLE_OK) {
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Error: rollback. */
|
||||
close_one(connssl, data);
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode gskit_connect_step2(struct connectdata * conn, int sockindex,
|
||||
bool nonblocking)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
Qso_OverlappedIO_t cstat;
|
||||
long timeout_ms;
|
||||
struct timeval stmv;
|
||||
CURLcode cc;
|
||||
|
||||
/* Poll or wait for end of SSL asynchronous handshake. */
|
||||
|
||||
for(;;) {
|
||||
timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
|
||||
if(timeout_ms < 0)
|
||||
timeout_ms = 0;
|
||||
stmv.tv_sec = timeout_ms / 1000;
|
||||
stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
|
||||
switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
|
||||
case 1: /* Operation complete. */
|
||||
break;
|
||||
case -1: /* An error occurred: handshake still in progress. */
|
||||
if(errno == EINTR) {
|
||||
if(nonblocking)
|
||||
return CURLE_OK;
|
||||
continue; /* Retry. */
|
||||
}
|
||||
if(errno != ETIME) {
|
||||
failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
|
||||
cancel_async_handshake(conn, sockindex);
|
||||
close_async_handshake(connssl);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
/* FALL INTO... */
|
||||
case 0: /* Handshake in progress, timeout occurred. */
|
||||
if(nonblocking)
|
||||
return CURLE_OK;
|
||||
cancel_async_handshake(conn, sockindex);
|
||||
close_async_handshake(connssl);
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
cc = gskit_status(data, cstat.returnValue, "SSL handshake",
|
||||
CURLE_SSL_CONNECT_ERROR);
|
||||
if(cc == CURLE_OK)
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
close_async_handshake(connssl);
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode gskit_connect_step3(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
const gsk_cert_data_elem * cdev;
|
||||
int cdec;
|
||||
const gsk_cert_data_elem * p;
|
||||
const char * cert = (const char *) NULL;
|
||||
const char * certend;
|
||||
int i;
|
||||
CURLcode cc;
|
||||
|
||||
/* SSL handshake done: gather certificate info and verify host. */
|
||||
|
||||
if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
|
||||
GSK_PARTNER_CERT_INFO,
|
||||
&cdev, &cdec),
|
||||
"gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
|
||||
CURLE_OK) {
|
||||
infof(data, "Server certificate:\n");
|
||||
p = cdev;
|
||||
for(i = 0; i++ < cdec; p++)
|
||||
switch (p->cert_data_id) {
|
||||
case CERT_BODY_DER:
|
||||
cert = p->cert_data_p;
|
||||
certend = cert + cdev->cert_data_l;
|
||||
break;
|
||||
case CERT_DN_PRINTABLE:
|
||||
infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
|
||||
break;
|
||||
case CERT_ISSUER_DN_PRINTABLE:
|
||||
infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
|
||||
break;
|
||||
case CERT_VALID_FROM:
|
||||
infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
|
||||
break;
|
||||
case CERT_VALID_TO:
|
||||
infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify host. */
|
||||
cc = Curl_verifyhost(conn, cert, certend);
|
||||
if(cc != CURLE_OK)
|
||||
return cc;
|
||||
|
||||
/* The only place GSKit can get the whole CA chain is a validation
|
||||
callback where no user data pointer is available. Therefore it's not
|
||||
possible to copy this chain into our structures for CAINFO.
|
||||
However the server certificate may be available, thus we can return
|
||||
info about it. */
|
||||
if(data->set.ssl.certinfo) {
|
||||
if(Curl_ssl_init_certinfo(data, 1))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(cert) {
|
||||
cc = Curl_extract_certinfo(conn, 0, cert, certend);
|
||||
if(cc != CURLE_OK)
|
||||
return cc;
|
||||
}
|
||||
}
|
||||
|
||||
connssl->connecting_state = ssl_connect_done;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
static CURLcode gskit_connect_common(struct connectdata * conn, int sockindex,
|
||||
bool nonblocking, bool * done)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
long timeout_ms;
|
||||
Qso_OverlappedIO_t cstat;
|
||||
CURLcode cc = CURLE_OK;
|
||||
|
||||
*done = connssl->state == ssl_connection_complete;
|
||||
if(*done)
|
||||
return CURLE_OK;
|
||||
|
||||
/* Step 1: create session, start handshake. */
|
||||
if(connssl->connecting_state == ssl_connect_1) {
|
||||
/* check allowed time left */
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* no need to continue if time already is up */
|
||||
failf(data, "SSL connection timeout");
|
||||
cc = CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
else
|
||||
cc = gskit_connect_step1(conn, sockindex);
|
||||
}
|
||||
|
||||
/* Step 2: check if handshake is over. */
|
||||
if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_2) {
|
||||
/* check allowed time left */
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* no need to continue if time already is up */
|
||||
failf(data, "SSL connection timeout");
|
||||
cc = CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
else
|
||||
cc = gskit_connect_step2(conn, sockindex, nonblocking);
|
||||
}
|
||||
|
||||
/* Step 3: gather certificate info, verify host. */
|
||||
if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_3)
|
||||
cc = gskit_connect_step3(conn, sockindex);
|
||||
|
||||
if(cc != CURLE_OK)
|
||||
close_one(connssl, data);
|
||||
else if(connssl->connecting_state == ssl_connect_done) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
conn->recv[sockindex] = gskit_recv;
|
||||
conn->send[sockindex] = gskit_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
|
||||
int sockindex,
|
||||
bool * done)
|
||||
{
|
||||
CURLcode cc;
|
||||
|
||||
cc = gskit_connect_common(conn, sockindex, TRUE, done);
|
||||
if(*done || cc != CURLE_OK)
|
||||
conn->ssl[sockindex].connecting_state = ssl_connect_1;
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
CURLcode retcode;
|
||||
bool done;
|
||||
|
||||
conn->ssl[sockindex].connecting_state = ssl_connect_1;
|
||||
retcode = gskit_connect_common(conn, sockindex, FALSE, &done);
|
||||
if(retcode)
|
||||
return retcode;
|
||||
|
||||
DEBUGASSERT(done);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
void Curl_gskit_close(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
struct SessionHandle * data = conn->data;
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
|
||||
if(connssl->use)
|
||||
close_one(connssl, data);
|
||||
}
|
||||
|
||||
|
||||
int Curl_gskit_close_all(struct SessionHandle * data)
|
||||
{
|
||||
/* Unimplemented. */
|
||||
(void) data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Curl_gskit_shutdown(struct connectdata * conn, int sockindex)
|
||||
{
|
||||
struct ssl_connect_data * connssl = &conn->ssl[sockindex];
|
||||
struct SessionHandle * data = conn->data;
|
||||
ssize_t nread;
|
||||
int what;
|
||||
int rc;
|
||||
char buf[120];
|
||||
|
||||
if(!connssl->handle)
|
||||
return 0;
|
||||
|
||||
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
|
||||
return 0;
|
||||
|
||||
close_one(connssl, data);
|
||||
rc = 0;
|
||||
what = Curl_socket_ready(conn->sock[sockindex],
|
||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||
|
||||
for(;;) {
|
||||
if(what < 0) {
|
||||
/* anything that gets here is fatally bad */
|
||||
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!what) { /* timeout */
|
||||
failf(data, "SSL shutdown timeout");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Something to read, let's do it and hope that it is the close
|
||||
notify alert from the server. No way to gsk_secure_soc_read() now, so
|
||||
use read(). */
|
||||
|
||||
nread = read(conn->sock[sockindex], buf, sizeof(buf));
|
||||
|
||||
if(nread < 0) {
|
||||
failf(data, "read: %s", strerror(errno));
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if(nread <= 0)
|
||||
break;
|
||||
|
||||
what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
size_t Curl_gskit_version(char * buffer, size_t size)
|
||||
{
|
||||
strncpy(buffer, "GSKit", size);
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
|
||||
int Curl_gskit_check_cxn(struct connectdata * cxn)
|
||||
{
|
||||
int err;
|
||||
int errlen;
|
||||
|
||||
/* The only thing that can be tested here is at the socket level. */
|
||||
|
||||
if(!cxn->ssl[FIRSTSOCKET].handle)
|
||||
return 0; /* connection has been closed */
|
||||
|
||||
err = 0;
|
||||
errlen = sizeof err;
|
||||
|
||||
if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
|
||||
(unsigned char *) &err, &errlen) ||
|
||||
errlen != sizeof err || err)
|
||||
return 0; /* connection has been closed */
|
||||
|
||||
return -1; /* connection status unknown */
|
||||
}
|
||||
|
||||
#endif /* USE_GSKIT */
|
64
lib/gskit.h
Normal file
64
lib/gskit.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef HEADER_CURL_GSKIT_H
|
||||
#define HEADER_CURL_GSKIT_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, 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_setup.h"
|
||||
|
||||
/*
|
||||
* This header should only be needed to get included by sslgen.c and gskit.c
|
||||
*/
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
int Curl_gskit_init(void);
|
||||
void Curl_gskit_cleanup(void);
|
||||
CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex);
|
||||
CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
|
||||
int sockindex, bool * done);
|
||||
void Curl_gskit_close(struct connectdata *conn, int sockindex);
|
||||
int Curl_gskit_close_all(struct SessionHandle * data);
|
||||
int Curl_gskit_shutdown(struct connectdata * conn, int sockindex);
|
||||
|
||||
size_t Curl_gskit_version(char * buffer, size_t size);
|
||||
int Curl_gskit_check_cxn(struct connectdata * cxn);
|
||||
|
||||
/* API setup for GSKit */
|
||||
#define curlssl_init Curl_gskit_init
|
||||
#define curlssl_cleanup Curl_gskit_cleanup
|
||||
#define curlssl_connect Curl_gskit_connect
|
||||
#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
|
||||
|
||||
/* No session handling for GSKit */
|
||||
#define curlssl_session_free(x) Curl_nop_stmt
|
||||
#define curlssl_close_all Curl_gskit_close_all
|
||||
#define curlssl_close Curl_gskit_close
|
||||
#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
|
||||
#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
|
||||
#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
|
||||
#define curlssl_engines_list(x) NULL
|
||||
#define curlssl_version Curl_gskit_version
|
||||
#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
|
||||
#define curlssl_data_pending(x,y) 0
|
||||
#endif /* USE_GSKIT */
|
||||
|
||||
#endif /* HEADER_CURL_GSKIT_H */
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -55,6 +55,10 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
|
||||
unsigned char *md5sum, /* output */
|
||||
size_t md5len);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for GnuTLS */
|
||||
#define curlssl_init Curl_gtls_init
|
||||
#define curlssl_cleanup Curl_gtls_cleanup
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -391,7 +391,7 @@ void Curl_hash_print(struct curl_hash *h,
|
||||
if(func)
|
||||
func(he->ptr);
|
||||
else
|
||||
fprintf(stderr, " [%p]", he->ptr);
|
||||
fprintf(stderr, " [%p]", (void *)he->ptr);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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,8 +22,9 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS)
|
||||
/* these two backends use functions from this file */
|
||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
|
||||
defined(USE_GSKIT)
|
||||
/* these backends use functions from this file */
|
||||
|
||||
#include "hostcheck.h"
|
||||
#include "rawstr.h"
|
||||
@@ -93,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SSLEAY or AXTLS */
|
||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
|
||||
|
31
lib/hostip.c
31
lib/hostip.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -140,6 +140,10 @@ struct curl_hash *Curl_global_host_cache_init(void)
|
||||
void Curl_global_host_cache_dtor(void)
|
||||
{
|
||||
if(host_cache_initialized) {
|
||||
/* first make sure that any custom "CURLOPT_RESOLVE" names are
|
||||
cleared off */
|
||||
Curl_hostcache_clean(NULL, &hostname_cache);
|
||||
/* then free the remaining hash completely */
|
||||
Curl_hash_clean(&hostname_cache);
|
||||
host_cache_initialized = 0;
|
||||
}
|
||||
@@ -681,12 +685,14 @@ clean_up:
|
||||
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
|
||||
* made, the struct may be destroyed due to pruning. It is important that only
|
||||
* one unlock is made for each Curl_resolv() call.
|
||||
*
|
||||
* May be called with 'data' == NULL for global cache.
|
||||
*/
|
||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
||||
{
|
||||
DEBUGASSERT(dns && (dns->inuse>0));
|
||||
|
||||
if(data->share)
|
||||
if(data && data->share)
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
dns->inuse--;
|
||||
@@ -697,7 +703,7 @@ void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
||||
free(dns);
|
||||
}
|
||||
|
||||
if(data->share)
|
||||
if(data && data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
}
|
||||
|
||||
@@ -734,22 +740,23 @@ static int hostcache_inuse(void *data, void *hc)
|
||||
return 1; /* free all entries */
|
||||
}
|
||||
|
||||
void Curl_hostcache_clean(struct SessionHandle *data)
|
||||
/*
|
||||
* Curl_hostcache_clean()
|
||||
*
|
||||
* This _can_ be called with 'data' == NULL but then of course no locking
|
||||
* can be done!
|
||||
*/
|
||||
|
||||
void Curl_hostcache_clean(struct SessionHandle *data,
|
||||
struct curl_hash *hash)
|
||||
{
|
||||
/* Entries added to the hostcache with the CURLOPT_RESOLVE function are
|
||||
* still present in the cache with the inuse counter set to 1. Detect them
|
||||
* and cleanup!
|
||||
*/
|
||||
Curl_hash_clean_with_criterium(data->dns.hostcache, data, hostcache_inuse);
|
||||
Curl_hash_clean_with_criterium(hash, data, hostcache_inuse);
|
||||
}
|
||||
|
||||
void Curl_hostcache_destroy(struct SessionHandle *data)
|
||||
{
|
||||
Curl_hostcache_clean(data);
|
||||
Curl_hash_destroy(data->dns.hostcache);
|
||||
data->dns.hostcachetype = HCACHE_NONE;
|
||||
data->dns.hostcache = NULL;
|
||||
}
|
||||
|
||||
CURLcode Curl_loadhostpairs(struct SessionHandle *data)
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -203,7 +203,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
|
||||
/*
|
||||
* Clean off entries from the cache
|
||||
*/
|
||||
void Curl_hostcache_clean(struct SessionHandle *data);
|
||||
void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
|
||||
|
||||
/*
|
||||
* Destroy the hostcache of this handle.
|
||||
|
@@ -25,14 +25,13 @@
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_md5.h"
|
||||
#include "http_digest.h"
|
||||
#include "strtok.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "curl_memory.h"
|
||||
#include "sslgen.h" /* for Curl_rand() */
|
||||
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
|
||||
#include "warnless.h"
|
||||
|
||||
@@ -283,7 +282,7 @@ static char *string_quoted(const char *source)
|
||||
++s;
|
||||
}
|
||||
|
||||
dest = (char *)malloc(n);
|
||||
dest = malloc(n);
|
||||
if(dest) {
|
||||
s = source;
|
||||
d = dest;
|
||||
@@ -310,14 +309,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
||||
unsigned char request_digest[33];
|
||||
unsigned char *md5this;
|
||||
unsigned char *ha1;
|
||||
unsigned char ha1[33];/* 32 digits and 1 zero byte */
|
||||
unsigned char ha2[33];/* 32 digits and 1 zero byte */
|
||||
char cnoncebuf[33];
|
||||
char *cnonce = NULL;
|
||||
size_t cnonce_sz = 0;
|
||||
char *tmp = NULL;
|
||||
struct timeval now;
|
||||
|
||||
char **allocuserpwd;
|
||||
size_t userlen;
|
||||
const char *userp;
|
||||
@@ -354,10 +351,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
authp = &data->state.authhost;
|
||||
}
|
||||
|
||||
if(*allocuserpwd) {
|
||||
Curl_safefree(*allocuserpwd);
|
||||
*allocuserpwd = NULL;
|
||||
}
|
||||
|
||||
/* not set means empty */
|
||||
if(!userp)
|
||||
@@ -376,10 +370,11 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
d->nc = 1;
|
||||
|
||||
if(!d->cnonce) {
|
||||
/* Generate a cnonce */
|
||||
now = Curl_tvnow();
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%32ld",
|
||||
(long)now.tv_sec + now.tv_usec);
|
||||
struct timeval now = Curl_tvnow();
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
|
||||
Curl_rand(data), Curl_rand(data),
|
||||
(unsigned int)now.tv_sec,
|
||||
(unsigned int)now.tv_usec);
|
||||
|
||||
rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
|
||||
&cnonce, &cnonce_sz);
|
||||
@@ -406,12 +401,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
|
||||
ha1 = malloc(33); /* 32 digits and 1 zero byte */
|
||||
if(!ha1)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
|
||||
if(d->algo == CURLDIGESTALGO_MD5SESS) {
|
||||
@@ -421,7 +411,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, (unsigned char *)tmp);
|
||||
free(tmp); /* free this again */
|
||||
Curl_safefree(tmp);
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
}
|
||||
|
||||
@@ -463,18 +453,16 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
TODO: replace md5 of empty string with entity-body for PUT/POST */
|
||||
unsigned char *md5this2 = (unsigned char *)
|
||||
aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
|
||||
free(md5this);
|
||||
Curl_safefree(md5this);
|
||||
md5this = md5this2;
|
||||
}
|
||||
|
||||
if(!md5this) {
|
||||
free(ha1);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, ha2);
|
||||
|
||||
if(d->qop) {
|
||||
@@ -492,13 +480,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
d->nonce,
|
||||
ha2);
|
||||
}
|
||||
free(ha1);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||
Curl_md5it(md5buf, md5this);
|
||||
free(md5this); /* free this again */
|
||||
Curl_safefree(md5this);
|
||||
md5_to_ascii(md5buf, request_digest);
|
||||
|
||||
/* for test case 64 (snooped from a Mozilla 1.3a request)
|
||||
@@ -515,7 +502,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
chracters.
|
||||
*/
|
||||
userp_quoted = string_quoted(userp);
|
||||
if(!*userp_quoted)
|
||||
if(!userp_quoted)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(d->qop) {
|
||||
@@ -559,7 +546,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
request_digest);
|
||||
}
|
||||
free(userp_quoted);
|
||||
Curl_safefree(userp_quoted);
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -595,29 +582,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
|
||||
static void digest_cleanup_one(struct digestdata *d)
|
||||
{
|
||||
if(d->nonce)
|
||||
free(d->nonce);
|
||||
d->nonce = NULL;
|
||||
|
||||
if(d->cnonce)
|
||||
free(d->cnonce);
|
||||
d->cnonce = NULL;
|
||||
|
||||
if(d->realm)
|
||||
free(d->realm);
|
||||
d->realm = NULL;
|
||||
|
||||
if(d->opaque)
|
||||
free(d->opaque);
|
||||
d->opaque = NULL;
|
||||
|
||||
if(d->qop)
|
||||
free(d->qop);
|
||||
d->qop = NULL;
|
||||
|
||||
if(d->algorithm)
|
||||
free(d->algorithm);
|
||||
d->algorithm = NULL;
|
||||
Curl_safefree(d->nonce);
|
||||
Curl_safefree(d->cnonce);
|
||||
Curl_safefree(d->realm);
|
||||
Curl_safefree(d->opaque);
|
||||
Curl_safefree(d->qop);
|
||||
Curl_safefree(d->algorithm);
|
||||
|
||||
d->nc = 0;
|
||||
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
|
||||
|
18
lib/imap.c
18
lib/imap.c
@@ -77,6 +77,7 @@
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "warnless.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -398,7 +399,7 @@ static void state(struct connectdata *conn, imapstate newstate)
|
||||
|
||||
if(imapc->state != newstate)
|
||||
infof(conn->data, "IMAP %p state change from %s to %s\n",
|
||||
imapc, names[imapc->state], names[newstate]);
|
||||
(void *)imapc, names[imapc->state], names[newstate]);
|
||||
#endif
|
||||
|
||||
imapc->state = newstate;
|
||||
@@ -1152,7 +1153,7 @@ static CURLcode imap_state_auth_digest_resp_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* Send an empty response */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "");
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
@@ -1694,8 +1695,7 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
* connection phase.
|
||||
*
|
||||
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
||||
* phase is done when this function returns, or FALSE is not. When called as
|
||||
* a part of the easy interface, it will always be TRUE.
|
||||
* phase is done when this function returns, or FALSE if not.
|
||||
*/
|
||||
static CURLcode imap_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
@@ -1781,7 +1781,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
state(conn, IMAP_FETCH_FINAL);
|
||||
else {
|
||||
/* End the APPEND command first by sending an empty line */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "");
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
|
||||
if(!result)
|
||||
state(conn, IMAP_APPEND_FINAL);
|
||||
}
|
||||
@@ -2062,14 +2062,15 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
char *taggedfmt;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
DEBUGASSERT(fmt);
|
||||
|
||||
/* Calculate the next command ID wrapping at 3 digits */
|
||||
imapc->cmdid = (imapc->cmdid + 1) % 1000;
|
||||
|
||||
/* Calculate the tag based on the connection ID and command ID */
|
||||
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
|
||||
'A' + (conn->connection_id % 26), imapc->cmdid);
|
||||
'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
|
||||
|
||||
/* Prefix the format with the tag */
|
||||
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
|
||||
@@ -2077,10 +2078,11 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Send the data with the tag */
|
||||
va_start(ap, fmt);
|
||||
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
Curl_safefree(taggedfmt);
|
||||
va_end(ap);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -260,7 +260,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
}
|
||||
server = ldapssl_init(conn->host.name, (int)conn->port, 1);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
@@ -301,7 +301,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
}
|
||||
server = ldap_init(conn->host.name, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
@@ -337,7 +337,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
else {
|
||||
server = ldap_init(conn->host.name, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%hu",
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.name, conn->port);
|
||||
status = CURLE_COULDNT_CONNECT;
|
||||
goto quit;
|
||||
|
32
lib/md5.c
32
lib/md5.c
@@ -90,16 +90,36 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
|
||||
# include <md5.h>
|
||||
# endif
|
||||
|
||||
#elif defined(__MAC_10_4) || defined(__IPHONE_5_0)
|
||||
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
|
||||
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
|
||||
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
|
||||
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
|
||||
|
||||
/* For Apple operating systems: CommonCrypto has the functions we need.
|
||||
The library's headers are even backward-compatible with OpenSSL's
|
||||
headers as long as we define COMMON_DIGEST_FOR_OPENSSL first.
|
||||
These functions are available on Tiger and later, as well as iOS 2.0
|
||||
and later. If you're building for an older cat, well, sorry.
|
||||
|
||||
These functions are available on Tiger and later, as well as iOS 5.0
|
||||
and later. If you're building for an older cat, well, sorry. */
|
||||
# define COMMON_DIGEST_FOR_OPENSSL
|
||||
Declaring the functions as static like this seems to be a bit more
|
||||
reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
|
||||
# include <CommonCrypto/CommonDigest.h>
|
||||
# define MD5_CTX CC_MD5_CTX
|
||||
|
||||
static void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
CC_MD5_Init(ctx);
|
||||
}
|
||||
|
||||
static void MD5_Update(MD5_CTX *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen)
|
||||
{
|
||||
CC_MD5_Update(ctx, input, inputLen);
|
||||
}
|
||||
|
||||
static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
|
||||
{
|
||||
CC_MD5_Final(digest, ctx);
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -185,8 +185,10 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
|
||||
}
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d malloc(%zd) = %p\n",
|
||||
source, line, wantedsize, mem ? mem->mem : 0);
|
||||
curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
|
||||
source, line, wantedsize,
|
||||
mem ? (void *)mem->mem : (void *)0);
|
||||
|
||||
return (mem ? mem->mem : NULL);
|
||||
}
|
||||
|
||||
@@ -212,7 +214,9 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
|
||||
source, line, wanted_elements, wanted_size, mem?mem->mem:0);
|
||||
source, line, wanted_elements, wanted_size,
|
||||
mem ? (void *)mem->mem : (void *)0);
|
||||
|
||||
return (mem ? mem->mem : NULL);
|
||||
}
|
||||
|
||||
@@ -234,11 +238,37 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
|
||||
source, line, str, len, mem);
|
||||
source, line, (void *)str, len, (void *)mem);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
|
||||
{
|
||||
wchar_t *mem;
|
||||
size_t wsiz, bsiz;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
if(countcheck("wcsdup", line, source))
|
||||
return NULL;
|
||||
|
||||
wsiz = wcslen(str) + 1;
|
||||
bsiz = wsiz * sizeof(wchar_t);
|
||||
|
||||
mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
|
||||
if(mem)
|
||||
memcpy(mem, str, bsiz);
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
|
||||
source, line, (void *)str, bsiz, (void *)mem);
|
||||
|
||||
return mem;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We provide a realloc() that accepts a NULL as pointer, which then
|
||||
performs a malloc(). In order to work with ares. */
|
||||
void *curl_dorealloc(void *ptr, size_t wantedsize,
|
||||
@@ -269,7 +299,8 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
|
||||
mem = (Curl_crealloc)(mem, size);
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
|
||||
source, line, ptr, wantedsize, mem?mem->mem:NULL);
|
||||
source, line, (void *)ptr, wantedsize,
|
||||
mem ? (void *)mem->mem : (void *)0);
|
||||
|
||||
if(mem) {
|
||||
mem->size = wantedsize;
|
||||
@@ -304,7 +335,7 @@ void curl_dofree(void *ptr, int line, const char *source)
|
||||
(Curl_cfree)(mem);
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d free(%p)\n", source, line, ptr);
|
||||
curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
|
||||
}
|
||||
|
||||
curl_socket_t curl_socket(int domain, int type, int protocol,
|
||||
@@ -317,8 +348,10 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
|
||||
"FD %s:%d socket() = %zd\n" ;
|
||||
|
||||
curl_socket_t sockfd = socket(domain, type, protocol);
|
||||
|
||||
if(source && (sockfd != CURL_SOCKET_BAD))
|
||||
curl_memlog(fmt, source, line, sockfd);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
@@ -334,8 +367,10 @@ int curl_socketpair(int domain, int type, int protocol,
|
||||
"FD %s:%d socketpair() = %zd %zd\n" ;
|
||||
|
||||
int res = socketpair(domain, type, protocol, socket_vector);
|
||||
|
||||
if(source && (0 == res))
|
||||
curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -351,9 +386,12 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
|
||||
|
||||
struct sockaddr *addr = (struct sockaddr *)saddr;
|
||||
curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
|
||||
|
||||
curl_socket_t sockfd = accept(s, addr, addrlen);
|
||||
|
||||
if(source && (sockfd != CURL_SOCKET_BAD))
|
||||
curl_memlog(fmt, source, line, sockfd);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
@@ -382,9 +420,11 @@ FILE *curl_fopen(const char *file, const char *mode,
|
||||
int line, const char *source)
|
||||
{
|
||||
FILE *res=fopen(file, mode);
|
||||
|
||||
if(source)
|
||||
curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
|
||||
source, line, file, mode, res);
|
||||
source, line, file, mode, (void *)res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -393,9 +433,11 @@ FILE *curl_fdopen(int filedes, const char *mode,
|
||||
int line, const char *source)
|
||||
{
|
||||
FILE *res=fdopen(filedes, mode);
|
||||
|
||||
if(source)
|
||||
curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
|
||||
source, line, filedes, mode, res);
|
||||
source, line, filedes, mode, (void *)res);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -407,9 +449,11 @@ int curl_fclose(FILE *file, int line, const char *source)
|
||||
assert(file != NULL);
|
||||
|
||||
res=fclose(file);
|
||||
|
||||
if(source)
|
||||
curl_memlog("FILE %s:%d fclose(%p)\n",
|
||||
source, line, file);
|
||||
source, line, (void *)file);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -46,6 +46,11 @@ CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
|
||||
const char *source);
|
||||
CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
|
||||
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
|
||||
const char *source);
|
||||
#endif
|
||||
|
||||
CURL_EXTERN void curl_memdebug(const char *logname);
|
||||
CURL_EXTERN void curl_memlimit(long limit);
|
||||
CURL_EXTERN void curl_memlog(const char *format, ...);
|
||||
@@ -84,6 +89,20 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
|
||||
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
|
||||
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
|
||||
|
||||
#ifdef WIN32
|
||||
# ifdef UNICODE
|
||||
# undef wcsdup
|
||||
# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
||||
# undef _wcsdup
|
||||
# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
||||
# else
|
||||
# undef _tcsdup
|
||||
# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define socket(domain,type,protocol)\
|
||||
curl_socket(domain,type,protocol,__LINE__,__FILE__)
|
||||
#undef accept /* for those with accept as a macro */
|
||||
|
@@ -40,7 +40,7 @@ my $url = 'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/
|
||||
# If the OpenSSL commandline is not in search path you can configure it here!
|
||||
my $openssl = 'openssl';
|
||||
|
||||
my $version = '1.18';
|
||||
my $version = '1.19';
|
||||
|
||||
$opt_w = 76; # default base64 encoded lines length
|
||||
|
||||
@@ -164,7 +164,7 @@ while (<TXT>) {
|
||||
if ($start_of_cert && /^CKA_LABEL UTF8 \"(.*)\"/) {
|
||||
$caname = $1;
|
||||
}
|
||||
my $untrusted = 0;
|
||||
my $untrusted = 1;
|
||||
if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) {
|
||||
my $data;
|
||||
while (<TXT>) {
|
||||
@@ -184,9 +184,8 @@ while (<TXT>) {
|
||||
# now scan the trust part for untrusted certs
|
||||
while (<TXT>) {
|
||||
last if (/^#/);
|
||||
if (/^CKA_TRUST_SERVER_AUTH\s+CK_TRUST\s+CKT_NSS_NOT_TRUSTED$/
|
||||
or /^CKA_TRUST_SERVER_AUTH\s+CK_TRUST\s+CKT_NSS_TRUST_UNKNOWN$/) {
|
||||
$untrusted = 1;
|
||||
if (/^CKA_TRUST_SERVER_AUTH\s+CK_TRUST\s+CKT_NSS_TRUSTED_DELEGATOR$/) {
|
||||
$untrusted = 0;
|
||||
}
|
||||
}
|
||||
if ($untrusted) {
|
||||
|
@@ -26,7 +26,7 @@
|
||||
'* Hacked by Guenter Knauf
|
||||
'***************************************************************************
|
||||
Option Explicit
|
||||
Const myVersion = "0.3.7"
|
||||
Const myVersion = "0.3.8"
|
||||
|
||||
Const myUrl = "http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1"
|
||||
|
||||
@@ -130,9 +130,8 @@ For i = 0 To UBound(myLines)
|
||||
myInsideCert = FALSE
|
||||
While (i < UBound(myLines)) And Not (myLines(i) = "#")
|
||||
i = i + 1
|
||||
If (InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED") Or _
|
||||
InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUST_UNKNOWN")) Then
|
||||
myUntrusted = TRUE
|
||||
If InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR") Then
|
||||
myUntrusted = FALSE
|
||||
End If
|
||||
Wend
|
||||
If (myUntrusted = TRUE) Then
|
||||
@@ -182,7 +181,7 @@ For i = 0 To UBound(myLines)
|
||||
End If
|
||||
If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then
|
||||
myInsideCert = TRUE
|
||||
myUntrusted = FALSE
|
||||
myUntrusted = TRUE
|
||||
myData = ""
|
||||
End If
|
||||
If InstrRev(myLines(i), "***** BEGIN LICENSE BLOCK *****") Then
|
||||
|
@@ -380,11 +380,11 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
|
||||
break;
|
||||
case 'x':
|
||||
vto[i].type = FORMAT_INT;
|
||||
flags |= FLAGS_HEX;
|
||||
flags |= FLAGS_HEX|FLAGS_UNSIGNED;
|
||||
break;
|
||||
case 'X':
|
||||
vto[i].type = FORMAT_INT;
|
||||
flags |= FLAGS_HEX|FLAGS_UPPER;
|
||||
flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
|
||||
break;
|
||||
case 'c':
|
||||
vto[i].type = FORMAT_INT;
|
||||
@@ -633,23 +633,23 @@ static int dprintf_formatf(
|
||||
OUTCHAR(' ');
|
||||
break;
|
||||
}
|
||||
if(p->flags & FLAGS_UNSIGNED) {
|
||||
/* Decimal unsigned integer. */
|
||||
base = 10;
|
||||
goto unsigned_number;
|
||||
}
|
||||
if(p->flags & FLAGS_OCTAL) {
|
||||
/* Octal unsigned integer. */
|
||||
base = 8;
|
||||
goto unsigned_number;
|
||||
}
|
||||
if(p->flags & FLAGS_HEX) {
|
||||
else if(p->flags & FLAGS_HEX) {
|
||||
/* Hexadecimal unsigned integer. */
|
||||
|
||||
digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
|
||||
base = 16;
|
||||
goto unsigned_number;
|
||||
}
|
||||
else if(p->flags & FLAGS_UNSIGNED) {
|
||||
/* Decimal unsigned integer. */
|
||||
base = 10;
|
||||
goto unsigned_number;
|
||||
}
|
||||
|
||||
/* Decimal integer. */
|
||||
base = 10;
|
||||
|
395
lib/multi.c
395
lib/multi.c
@@ -68,7 +68,7 @@
|
||||
((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
|
||||
|
||||
static void singlesocket(struct Curl_multi *multi,
|
||||
struct Curl_one_easy *easy);
|
||||
struct SessionHandle *easy);
|
||||
static int update_timer(struct Curl_multi *multi);
|
||||
|
||||
static bool isHandleAtHead(struct SessionHandle *handle,
|
||||
@@ -105,7 +105,7 @@ static const char * const statename[]={
|
||||
static void multi_freetimeout(void *a, void *b);
|
||||
|
||||
/* always use this function to change state, to make debugging easier */
|
||||
static void mstate(struct Curl_one_easy *easy, CURLMstate state
|
||||
static void mstate(struct SessionHandle *easy, CURLMstate state
|
||||
#ifdef DEBUGBUILD
|
||||
, int lineno
|
||||
#endif
|
||||
@@ -114,29 +114,29 @@ static void mstate(struct Curl_one_easy *easy, CURLMstate state
|
||||
#ifdef DEBUGBUILD
|
||||
long connection_id = -5000;
|
||||
#endif
|
||||
CURLMstate oldstate = easy->state;
|
||||
CURLMstate oldstate = easy->mstate;
|
||||
|
||||
if(oldstate == state)
|
||||
/* don't bother when the new state is the same as the old state */
|
||||
return;
|
||||
|
||||
easy->state = state;
|
||||
easy->mstate = state;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
if(easy->state >= CURLM_STATE_CONNECT_PEND &&
|
||||
easy->state < CURLM_STATE_COMPLETED) {
|
||||
if(easy->mstate >= CURLM_STATE_CONNECT_PEND &&
|
||||
easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
if(easy->easy_conn)
|
||||
connection_id = easy->easy_conn->connection_id;
|
||||
|
||||
infof(easy->easy_handle,
|
||||
infof(easy,
|
||||
"STATE: %s => %s handle %p; line %d (connection #%ld) \n",
|
||||
statename[oldstate], statename[easy->state],
|
||||
(char *)easy, lineno, connection_id);
|
||||
statename[oldstate], statename[easy->mstate],
|
||||
(void *)easy, lineno, connection_id);
|
||||
}
|
||||
#endif
|
||||
if(state == CURLM_STATE_COMPLETED)
|
||||
/* changing to COMPLETED means there's one less easy handle 'alive' */
|
||||
easy->easy_handle->multi->num_alive--;
|
||||
easy->multi->num_alive--;
|
||||
}
|
||||
|
||||
#ifndef DEBUGBUILD
|
||||
@@ -307,12 +307,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
|
||||
if(!multi->msglist)
|
||||
goto error;
|
||||
|
||||
/* Let's make the doubly-linked list a circular list. This makes
|
||||
the linked list code simpler and allows inserting at the end
|
||||
with less work (we didn't keep a tail pointer before). */
|
||||
multi->easy.next = &multi->easy;
|
||||
multi->easy.prev = &multi->easy;
|
||||
|
||||
multi->max_pipeline_length = 5;
|
||||
return (CURLM *) multi;
|
||||
|
||||
@@ -340,7 +334,6 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
CURL *easy_handle)
|
||||
{
|
||||
struct curl_llist *timeoutlist;
|
||||
struct Curl_one_easy *easy;
|
||||
struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
|
||||
struct SessionHandle *data = (struct SessionHandle *)easy_handle;
|
||||
struct SessionHandle *new_closure = NULL;
|
||||
@@ -354,8 +347,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
if(!GOOD_EASY_HANDLE(easy_handle))
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
|
||||
/* Prevent users from adding same easy handle more than
|
||||
once and prevent adding to more than one multi stack */
|
||||
/* Prevent users from adding same easy handle more than once and prevent
|
||||
adding to more than one multi stack */
|
||||
if(data->multi)
|
||||
/* possibly we should create a new unique error code for this condition */
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
@@ -365,19 +358,11 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
if(!timeoutlist)
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
|
||||
/* Allocate new node for the doubly-linked circular list of
|
||||
Curl_one_easy structs that holds pointers to easy handles */
|
||||
easy = calloc(1, sizeof(struct Curl_one_easy));
|
||||
if(!easy) {
|
||||
Curl_llist_destroy(timeoutlist, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* In case multi handle has no hostcache yet, allocate one */
|
||||
if(!multi->hostcache) {
|
||||
hostcache = Curl_mk_dnscache();
|
||||
if(!hostcache) {
|
||||
free(easy);
|
||||
free(data);
|
||||
Curl_llist_destroy(timeoutlist, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -389,7 +374,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
new_closure = (struct SessionHandle *)curl_easy_init();
|
||||
if(!new_closure) {
|
||||
Curl_hash_destroy(hostcache);
|
||||
free(easy);
|
||||
free(data);
|
||||
Curl_llist_destroy(timeoutlist, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -420,44 +405,51 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
timeoutlist = NULL;
|
||||
|
||||
/* set the easy handle */
|
||||
easy->easy_handle = data;
|
||||
multistate(easy, CURLM_STATE_INIT);
|
||||
|
||||
/* set the back pointer to one_easy to assist in removal */
|
||||
easy->easy_handle->multi_pos = easy;
|
||||
multistate(data, CURLM_STATE_INIT);
|
||||
|
||||
if((data->set.global_dns_cache) &&
|
||||
(data->dns.hostcachetype != HCACHE_GLOBAL)) {
|
||||
/* global dns cache was requested but still isn't */
|
||||
struct curl_hash *global = Curl_global_host_cache_init();
|
||||
if(global) {
|
||||
/* only do this if the global cache init works */
|
||||
data->dns.hostcache = global;
|
||||
data->dns.hostcachetype = HCACHE_GLOBAL;
|
||||
}
|
||||
}
|
||||
/* for multi interface connections, we share DNS cache automatically if the
|
||||
easy handle's one is currently not set. */
|
||||
if(!easy->easy_handle->dns.hostcache ||
|
||||
(easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
|
||||
easy->easy_handle->dns.hostcache = multi->hostcache;
|
||||
easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
|
||||
else if(!data->dns.hostcache ||
|
||||
(data->dns.hostcachetype == HCACHE_NONE)) {
|
||||
data->dns.hostcache = multi->hostcache;
|
||||
data->dns.hostcachetype = HCACHE_MULTI;
|
||||
}
|
||||
|
||||
/* Point to the multi's connection cache */
|
||||
easy->easy_handle->state.conn_cache = multi->conn_cache;
|
||||
data->state.conn_cache = multi->conn_cache;
|
||||
|
||||
/* This adds the new entry at the 'end' of the doubly-linked circular
|
||||
list of Curl_one_easy structs to try and maintain a FIFO queue so
|
||||
list of SessionHandle structs to try and maintain a FIFO queue so
|
||||
the pipelined requests are in order. */
|
||||
|
||||
/* We add this new entry last in the list. We make our 'next' point to the
|
||||
'first' struct and our 'prev' point to the previous 'prev' */
|
||||
easy->next = &multi->easy;
|
||||
easy->prev = multi->easy.prev;
|
||||
/* We add this new entry last in the list. */
|
||||
|
||||
/* make 'easy' the last node in the chain */
|
||||
multi->easy.prev = easy;
|
||||
|
||||
/* if there was a prev node, make sure its 'next' pointer links to
|
||||
the new node */
|
||||
easy->prev->next = easy;
|
||||
data->next = NULL; /* end of the line */
|
||||
if(multi->easyp) {
|
||||
struct SessionHandle *last = multi->easylp;
|
||||
last->next = data;
|
||||
data->prev = last;
|
||||
multi->easylp = data; /* the new last node */
|
||||
}
|
||||
else {
|
||||
/* first node, make both prev and next be NULL! */
|
||||
data->next = NULL;
|
||||
data->prev = NULL;
|
||||
multi->easylp = multi->easyp = data; /* both first and last */
|
||||
}
|
||||
|
||||
/* make the SessionHandle refer back to this multi handle */
|
||||
Curl_easy_addmulti(easy_handle, multi_handle);
|
||||
|
||||
/* make the SessionHandle struct refer back to this struct */
|
||||
easy->easy_handle->set.one_easy = easy;
|
||||
Curl_easy_addmulti(data, multi_handle);
|
||||
|
||||
/* Set the timeout for this handle to expire really soon so that it will
|
||||
be taken care of even when this handle is added in the midst of operation
|
||||
@@ -465,7 +457,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
sockets that time-out or have actions will be dealt with. Since this
|
||||
handle has no action yet, we make sure it times out to get things to
|
||||
happen. */
|
||||
Curl_expire(easy->easy_handle, 1);
|
||||
Curl_expire(data, 1);
|
||||
|
||||
/* increase the node-counter */
|
||||
multi->num_easy++;
|
||||
@@ -509,8 +501,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *data = curl_handle;
|
||||
struct SessionHandle *easy = curl_handle;
|
||||
struct SessionHandle *data = easy;
|
||||
|
||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
@@ -520,13 +512,10 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
if(!GOOD_EASY_HANDLE(curl_handle))
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
|
||||
/* pick-up from the 'curl_handle' the kept position in the list */
|
||||
easy = data->multi_pos;
|
||||
|
||||
if(easy) {
|
||||
bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
|
||||
bool premature = (easy->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
|
||||
bool easy_owns_conn = (easy->easy_conn &&
|
||||
(easy->easy_conn->data == easy->easy_handle)) ?
|
||||
(easy->easy_conn->data == easy)) ?
|
||||
TRUE : FALSE;
|
||||
|
||||
/* If the 'state' is not INIT or COMPLETED, we might need to do something
|
||||
@@ -539,21 +528,21 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
if(easy->easy_conn &&
|
||||
(easy->easy_conn->send_pipe->size +
|
||||
easy->easy_conn->recv_pipe->size > 1) &&
|
||||
easy->state > CURLM_STATE_WAITDO &&
|
||||
easy->state < CURLM_STATE_COMPLETED) {
|
||||
easy->mstate > CURLM_STATE_WAITDO &&
|
||||
easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
/* If the handle is in a pipeline and has started sending off its
|
||||
request but not received its response yet, we need to close
|
||||
connection. */
|
||||
easy->easy_conn->bits.close = TRUE;
|
||||
/* Set connection owner so that Curl_done() closes it.
|
||||
We can sefely do this here since connection is killed. */
|
||||
easy->easy_conn->data = easy->easy_handle;
|
||||
easy->easy_conn->data = easy;
|
||||
}
|
||||
|
||||
/* The timer must be shut down before easy->multi is set to NULL,
|
||||
else the timenode will remain in the splay tree after
|
||||
curl_easy_cleanup is called. */
|
||||
Curl_expire(easy->easy_handle, 0);
|
||||
Curl_expire(easy, 0);
|
||||
|
||||
/* destroy the timeout list that is held in the easy handle */
|
||||
if(data->state.timeoutlist) {
|
||||
@@ -561,10 +550,10 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
data->state.timeoutlist = NULL;
|
||||
}
|
||||
|
||||
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
|
||||
if(easy->dns.hostcachetype == HCACHE_MULTI) {
|
||||
/* stop using the multi handle's DNS cache */
|
||||
easy->easy_handle->dns.hostcache = NULL;
|
||||
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
||||
easy->dns.hostcache = NULL;
|
||||
easy->dns.hostcachetype = HCACHE_NONE;
|
||||
}
|
||||
|
||||
if(easy->easy_conn) {
|
||||
@@ -582,16 +571,16 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
}
|
||||
else
|
||||
/* Clear connection pipelines, if Curl_done above was not called */
|
||||
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
|
||||
Curl_getoff_all_pipelines(easy, easy->easy_conn);
|
||||
}
|
||||
|
||||
/* as this was using a shared connection cache we clear the pointer
|
||||
to that since we're not part of that multi handle anymore */
|
||||
easy->easy_handle->state.conn_cache = NULL;
|
||||
easy->state.conn_cache = NULL;
|
||||
|
||||
/* change state without using multistate(), only to make singlesocket() do
|
||||
what we want */
|
||||
easy->state = CURLM_STATE_COMPLETED;
|
||||
easy->mstate = CURLM_STATE_COMPLETED;
|
||||
singlesocket(multi, easy); /* to let the application know what sockets
|
||||
that vanish with this handle */
|
||||
|
||||
@@ -601,7 +590,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
easy->easy_conn = NULL;
|
||||
}
|
||||
|
||||
Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
|
||||
Curl_easy_addmulti(easy, NULL); /* clear the association
|
||||
to this multi handle */
|
||||
|
||||
{
|
||||
@@ -612,7 +601,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
for(e = multi->msglist->head; e; e = e->next) {
|
||||
struct Curl_message *msg = e->ptr;
|
||||
|
||||
if(msg->extmsg.easy_handle == easy->easy_handle) {
|
||||
if(msg->extmsg.easy_handle == easy) {
|
||||
Curl_llist_remove(multi->msglist, e, NULL);
|
||||
/* there can only be one from this specific handle */
|
||||
break;
|
||||
@@ -623,18 +612,17 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
/* make the previous node point to our next */
|
||||
if(easy->prev)
|
||||
easy->prev->next = easy->next;
|
||||
else
|
||||
multi->easyp = easy->next; /* point to first node */
|
||||
|
||||
/* make our next point to our previous node */
|
||||
if(easy->next)
|
||||
easy->next->prev = easy->prev;
|
||||
|
||||
easy->easy_handle->set.one_easy = NULL; /* detached */
|
||||
|
||||
/* Null the position in the controlling structure */
|
||||
easy->easy_handle->multi_pos = NULL;
|
||||
else
|
||||
multi->easylp = easy->prev; /* point to last node */
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
We do not touch the easy handle here! */
|
||||
free(easy);
|
||||
|
||||
multi->num_easy--; /* one less to care about now */
|
||||
|
||||
@@ -652,10 +640,7 @@ bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
|
||||
|
||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data)
|
||||
{
|
||||
struct Curl_one_easy *one_easy = data->set.one_easy;
|
||||
|
||||
if(one_easy)
|
||||
one_easy->easy_conn = NULL;
|
||||
data->easy_conn = NULL;
|
||||
}
|
||||
|
||||
static int waitconnect_getsock(struct connectdata *conn,
|
||||
@@ -685,7 +670,7 @@ static int domore_getsock(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* returns bitmapped flags for this handle and its sockets */
|
||||
static int multi_getsock(struct Curl_one_easy *easy,
|
||||
static int multi_getsock(struct SessionHandle *easy,
|
||||
curl_socket_t *socks, /* points to numsocks number
|
||||
of sockets */
|
||||
int numsocks)
|
||||
@@ -695,16 +680,16 @@ static int multi_getsock(struct Curl_one_easy *easy,
|
||||
happen when this is called from curl_multi_remove_handle() =>
|
||||
singlesocket() => multi_getsock().
|
||||
*/
|
||||
if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
|
||||
if(easy->state.pipe_broke || !easy->easy_conn)
|
||||
return 0;
|
||||
|
||||
if(easy->state > CURLM_STATE_CONNECT &&
|
||||
easy->state < CURLM_STATE_COMPLETED) {
|
||||
if(easy->mstate > CURLM_STATE_CONNECT &&
|
||||
easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
/* Set up ownership correctly */
|
||||
easy->easy_conn->data = easy->easy_handle;
|
||||
easy->easy_conn->data = easy;
|
||||
}
|
||||
|
||||
switch(easy->state) {
|
||||
switch(easy->mstate) {
|
||||
default:
|
||||
#if 0 /* switch back on these cases to get the compiler to check for all enums
|
||||
to be present */
|
||||
@@ -756,7 +741,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
Some easy handles may not have connected to the remote host yet,
|
||||
and then we must make sure that is done. */
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *easy;
|
||||
int this_max_fd=-1;
|
||||
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
|
||||
int bitmap;
|
||||
@@ -766,8 +751,8 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
@@ -805,7 +790,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
int *ret)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *easy;
|
||||
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
|
||||
int bitmap;
|
||||
unsigned int i;
|
||||
@@ -825,8 +810,8 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
timeout_ms = (int)timeout_internal;
|
||||
|
||||
/* Count up how many fds we have from the multi handle */
|
||||
easy=multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
@@ -863,8 +848,8 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
|
||||
if(curlfds) {
|
||||
/* Add the curl handles to our pollfds first */
|
||||
easy=multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
@@ -904,9 +889,30 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
++nfds;
|
||||
}
|
||||
|
||||
if(nfds)
|
||||
if(nfds) {
|
||||
/* wait... */
|
||||
i = Curl_poll(ufds, nfds, timeout_ms);
|
||||
|
||||
if(i) {
|
||||
unsigned int j;
|
||||
/* copy revents results from the poll to the curl_multi_wait poll
|
||||
struct, the bit values of the actual underlying poll() implementation
|
||||
may not be the same as the ones in the public libcurl API! */
|
||||
for(j = 0; j < extra_nfds; j++) {
|
||||
unsigned short mask = 0;
|
||||
unsigned r = ufds[curlfds + j].revents;
|
||||
|
||||
if(r & POLLIN)
|
||||
mask |= CURL_WAIT_POLLIN;
|
||||
if(r & POLLOUT)
|
||||
mask |= CURL_WAIT_POLLOUT;
|
||||
if(r & POLLPRI)
|
||||
mask |= CURL_WAIT_POLLPRI;
|
||||
|
||||
extra_fds[j].revents = mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
@@ -918,7 +924,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
|
||||
static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct timeval now,
|
||||
struct Curl_one_easy *easy)
|
||||
struct SessionHandle *easy)
|
||||
{
|
||||
struct Curl_message *msg = NULL;
|
||||
bool connected;
|
||||
@@ -930,11 +936,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct SingleRequest *k;
|
||||
struct SessionHandle *data;
|
||||
long timeout_ms;
|
||||
int control;
|
||||
|
||||
if(!GOOD_EASY_HANDLE(easy->easy_handle))
|
||||
if(!GOOD_EASY_HANDLE(easy))
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
|
||||
data = easy->easy_handle;
|
||||
data = easy;
|
||||
|
||||
do {
|
||||
/* this is a single-iteration do-while loop just to allow a
|
||||
@@ -945,9 +952,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
we're using gets cleaned up and we're left with nothing. */
|
||||
if(data->state.pipe_broke) {
|
||||
infof(data, "Pipe broke: handle 0x%p, url = %s\n",
|
||||
easy, data->state.path);
|
||||
(void *)easy, data->state.path);
|
||||
|
||||
if(easy->state < CURLM_STATE_COMPLETED) {
|
||||
if(easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
/* Head back to the CONNECT state */
|
||||
multistate(easy, CURLM_STATE_CONNECT);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
@@ -960,36 +967,36 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
|
||||
if(!easy->easy_conn &&
|
||||
easy->state > CURLM_STATE_CONNECT &&
|
||||
easy->state < CURLM_STATE_DONE) {
|
||||
easy->mstate > CURLM_STATE_CONNECT &&
|
||||
easy->mstate < CURLM_STATE_DONE) {
|
||||
/* In all these states, the code will blindly access 'easy->easy_conn'
|
||||
so this is precaution that it isn't NULL. And it silences static
|
||||
analyzers. */
|
||||
failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
|
||||
failf(data, "In state %d with no easy_conn, bail out!\n", easy->mstate);
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
|
||||
easy->state < CURLM_STATE_COMPLETED)
|
||||
if(easy->easy_conn && easy->mstate > CURLM_STATE_CONNECT &&
|
||||
easy->mstate < CURLM_STATE_COMPLETED)
|
||||
/* Make sure we set the connection's current owner */
|
||||
easy->easy_conn->data = data;
|
||||
|
||||
if(easy->easy_conn &&
|
||||
(easy->state >= CURLM_STATE_CONNECT) &&
|
||||
(easy->state < CURLM_STATE_COMPLETED)) {
|
||||
(easy->mstate >= CURLM_STATE_CONNECT) &&
|
||||
(easy->mstate < CURLM_STATE_COMPLETED)) {
|
||||
/* we need to wait for the connect state as only then is the start time
|
||||
stored, but we must not check already completed handles */
|
||||
|
||||
timeout_ms = Curl_timeleft(data, &now,
|
||||
(easy->state <= CURLM_STATE_WAITDO)?
|
||||
(easy->mstate <= CURLM_STATE_WAITDO)?
|
||||
TRUE:FALSE);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* Handle timed out */
|
||||
if(easy->state == CURLM_STATE_WAITRESOLVE)
|
||||
if(easy->mstate == CURLM_STATE_WAITRESOLVE)
|
||||
failf(data, "Resolving timed out after %ld milliseconds",
|
||||
Curl_tvdiff(now, data->progress.t_startsingle));
|
||||
else if(easy->state == CURLM_STATE_WAITCONNECT)
|
||||
else if(easy->mstate == CURLM_STATE_WAITCONNECT)
|
||||
failf(data, "Connection timed out after %ld milliseconds",
|
||||
Curl_tvdiff(now, data->progress.t_startsingle));
|
||||
else {
|
||||
@@ -1010,7 +1017,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
}
|
||||
|
||||
switch(easy->state) {
|
||||
switch(easy->mstate) {
|
||||
case CURLM_STATE_INIT:
|
||||
/* init this transfer. */
|
||||
easy->result=Curl_pretransfer(data);
|
||||
@@ -1210,12 +1217,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
case CURLM_STATE_WAITDO:
|
||||
/* Wait for our turn to DO when we're pipelining requests */
|
||||
#ifdef DEBUGBUILD
|
||||
infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
|
||||
infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
|
||||
easy->easy_conn->connection_id,
|
||||
easy->easy_conn->send_pipe->size,
|
||||
easy->easy_conn->writechannel_inuse?1:0,
|
||||
easy->easy_conn->writechannel_inuse?"TRUE":"FALSE",
|
||||
isHandleAtHead(data,
|
||||
easy->easy_conn->send_pipe)?1:0);
|
||||
easy->easy_conn->send_pipe)?"TRUE":"FALSE");
|
||||
#endif
|
||||
if(!easy->easy_conn->writechannel_inuse &&
|
||||
isHandleAtHead(data,
|
||||
@@ -1360,13 +1367,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/*
|
||||
* When we are connected, DO MORE and then go DO_DONE
|
||||
*/
|
||||
easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
|
||||
easy->result = Curl_do_more(easy->easy_conn, &control);
|
||||
|
||||
/* No need to remove this handle from the send pipeline here since that
|
||||
is done in Curl_done() */
|
||||
if(CURLE_OK == easy->result) {
|
||||
if(dophase_done) {
|
||||
multistate(easy, CURLM_STATE_DO_DONE);
|
||||
if(control) {
|
||||
/* if positive, advance to DO_DONE
|
||||
if negative, go back to DOING */
|
||||
multistate(easy, control==1?
|
||||
CURLM_STATE_DO_DONE:
|
||||
CURLM_STATE_DOING);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
else
|
||||
@@ -1402,12 +1413,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
#ifdef DEBUGBUILD
|
||||
else {
|
||||
infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
|
||||
infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
|
||||
easy->easy_conn->connection_id,
|
||||
easy->easy_conn->recv_pipe->size,
|
||||
easy->easy_conn->readchannel_inuse?1:0,
|
||||
easy->easy_conn->readchannel_inuse?"TRUE":"FALSE",
|
||||
isHandleAtHead(data,
|
||||
easy->easy_conn->recv_pipe)?1:0);
|
||||
easy->easy_conn->recv_pipe)?"TRUE":"FALSE");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -1641,7 +1652,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if(easy->state < CURLM_STATE_COMPLETED) {
|
||||
if(easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
if(CURLE_OK != easy->result) {
|
||||
/*
|
||||
* If an error was returned, and we aren't in completed state now,
|
||||
@@ -1674,7 +1685,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
easy->easy_conn = NULL;
|
||||
}
|
||||
}
|
||||
else if(easy->state == CURLM_STATE_CONNECT) {
|
||||
else if(easy->mstate == CURLM_STATE_CONNECT) {
|
||||
/* Curl_connect() failed */
|
||||
(void)Curl_posttransfer(data);
|
||||
}
|
||||
@@ -1688,14 +1699,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
easy->easy_conn->bits.close = TRUE;
|
||||
|
||||
/* if not yet in DONE state, go there, otherwise COMPLETED */
|
||||
multistate(easy, (easy->state < CURLM_STATE_DONE)?
|
||||
multistate(easy, (easy->mstate < CURLM_STATE_DONE)?
|
||||
CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
}
|
||||
} WHILE_FALSE; /* just to break out from! */
|
||||
|
||||
if(CURLM_STATE_COMPLETED == easy->state) {
|
||||
if(CURLM_STATE_COMPLETED == easy->mstate) {
|
||||
/* now fill in the Curl_message with this info */
|
||||
msg = &easy->msg;
|
||||
|
||||
@@ -1715,7 +1726,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *easy;
|
||||
CURLMcode returncode=CURLM_OK;
|
||||
struct Curl_tree *t;
|
||||
struct timeval now = Curl_tvnow();
|
||||
@@ -1723,12 +1734,12 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
CURLMcode result;
|
||||
struct WildcardData *wc = &easy->easy_handle->wildcard;
|
||||
struct WildcardData *wc = &easy->wildcard;
|
||||
|
||||
if(easy->easy_handle->set.wildcardmatch) {
|
||||
if(easy->set.wildcardmatch) {
|
||||
if(!wc->filelist) {
|
||||
CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
|
||||
if(ret)
|
||||
@@ -1740,7 +1751,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
result = multi_runsingle(multi, now, easy);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
|
||||
if(easy->easy_handle->set.wildcardmatch) {
|
||||
if(easy->set.wildcardmatch) {
|
||||
/* destruct wildcard structures if it is needed */
|
||||
if(wc->state == CURLWC_DONE || result)
|
||||
Curl_wildcard_dtor(wc);
|
||||
@@ -1796,8 +1807,8 @@ static void close_all_connections(struct Curl_multi *multi)
|
||||
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct Curl_one_easy *nexteasy;
|
||||
struct SessionHandle *easy;
|
||||
struct SessionHandle *nexteasy;
|
||||
|
||||
if(GOOD_MULTI_HANDLE(multi)) {
|
||||
multi->type = 0; /* not good anymore */
|
||||
@@ -1807,7 +1818,8 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
|
||||
if(multi->closure_handle) {
|
||||
multi->closure_handle->dns.hostcache = multi->hostcache;
|
||||
Curl_hostcache_clean(multi->closure_handle);
|
||||
Curl_hostcache_clean(multi->closure_handle,
|
||||
multi->closure_handle->dns.hostcache);
|
||||
|
||||
Curl_close(multi->closure_handle);
|
||||
multi->closure_handle = NULL;
|
||||
@@ -1824,22 +1836,21 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
multi->msglist = NULL;
|
||||
|
||||
/* remove all easy handles */
|
||||
easy = multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
easy = multi->easyp;
|
||||
while(easy) {
|
||||
nexteasy=easy->next;
|
||||
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
|
||||
if(easy->dns.hostcachetype == HCACHE_MULTI) {
|
||||
/* clear out the usage of the shared DNS cache */
|
||||
Curl_hostcache_clean(easy->easy_handle);
|
||||
easy->easy_handle->dns.hostcache = NULL;
|
||||
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
||||
Curl_hostcache_clean(easy, easy->dns.hostcache);
|
||||
easy->dns.hostcache = NULL;
|
||||
easy->dns.hostcachetype = HCACHE_NONE;
|
||||
}
|
||||
|
||||
/* Clear the pointer to the connection cache */
|
||||
easy->easy_handle->state.conn_cache = NULL;
|
||||
easy->state.conn_cache = NULL;
|
||||
|
||||
Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
|
||||
Curl_easy_addmulti(easy, NULL); /* clear the association */
|
||||
|
||||
free(easy);
|
||||
easy = nexteasy;
|
||||
}
|
||||
|
||||
@@ -1901,7 +1912,7 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
|
||||
* call the callback accordingly.
|
||||
*/
|
||||
static void singlesocket(struct Curl_multi *multi,
|
||||
struct Curl_one_easy *easy)
|
||||
struct SessionHandle *easy)
|
||||
{
|
||||
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
|
||||
int i;
|
||||
@@ -1909,7 +1920,6 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
curl_socket_t s;
|
||||
int num;
|
||||
unsigned int curraction;
|
||||
struct Curl_one_easy *easy_by_hash;
|
||||
bool remove_sock_from_hash;
|
||||
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
|
||||
@@ -1947,7 +1957,7 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
}
|
||||
else {
|
||||
/* this is a socket we didn't have before, add it! */
|
||||
entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
|
||||
entry = sh_addentry(multi->sockhash, s, easy);
|
||||
if(!entry)
|
||||
/* fatal */
|
||||
return;
|
||||
@@ -1955,7 +1965,7 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
|
||||
/* we know (entry != NULL) at this point, see the logic above */
|
||||
if(multi->socket_cb)
|
||||
multi->socket_cb(easy->easy_handle,
|
||||
multi->socket_cb(easy,
|
||||
s,
|
||||
action,
|
||||
multi->socket_userp,
|
||||
@@ -1988,10 +1998,7 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
/* check if the socket to be removed serves a connection which has
|
||||
other easy-s in a pipeline. In this case the socket should not be
|
||||
removed. */
|
||||
struct connectdata *easy_conn;
|
||||
|
||||
easy_by_hash = entry->easy->multi_pos;
|
||||
easy_conn = easy_by_hash->easy_conn;
|
||||
struct connectdata *easy_conn = easy->easy_conn;
|
||||
if(easy_conn) {
|
||||
if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
|
||||
/* the handle should not be removed from the pipe yet */
|
||||
@@ -2000,8 +2007,8 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
/* Update the sockhash entry to instead point to the next in line
|
||||
for the recv_pipe, or the first (in case this particular easy
|
||||
isn't already) */
|
||||
if(entry->easy == easy->easy_handle) {
|
||||
if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
|
||||
if(entry->easy == easy) {
|
||||
if(isHandleAtHead(easy, easy_conn->recv_pipe))
|
||||
entry->easy = easy_conn->recv_pipe->head->next->ptr;
|
||||
else
|
||||
entry->easy = easy_conn->recv_pipe->head->ptr;
|
||||
@@ -2014,8 +2021,8 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
/* Update the sockhash entry to instead point to the next in line
|
||||
for the send_pipe, or the first (in case this particular easy
|
||||
isn't already) */
|
||||
if(entry->easy == easy->easy_handle) {
|
||||
if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
|
||||
if(entry->easy == easy) {
|
||||
if(isHandleAtHead(easy, easy_conn->send_pipe))
|
||||
entry->easy = easy_conn->send_pipe->head->next->ptr;
|
||||
else
|
||||
entry->easy = easy_conn->send_pipe->head->ptr;
|
||||
@@ -2036,7 +2043,7 @@ static void singlesocket(struct Curl_multi *multi,
|
||||
if(remove_sock_from_hash) {
|
||||
/* in this case 'entry' is always non-NULL */
|
||||
if(multi->socket_cb)
|
||||
multi->socket_cb(easy->easy_handle,
|
||||
multi->socket_cb(easy,
|
||||
s,
|
||||
CURL_POLL_REMOVE,
|
||||
multi->socket_userp,
|
||||
@@ -2157,16 +2164,16 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
struct timeval now = Curl_tvnow();
|
||||
|
||||
if(checkall) {
|
||||
struct Curl_one_easy *easyp;
|
||||
struct SessionHandle *easy;
|
||||
/* *perform() deals with running_handles on its own */
|
||||
result = curl_multi_perform(multi, running_handles);
|
||||
|
||||
/* walk through each easy handle and do the socket state change magic
|
||||
and callbacks */
|
||||
easyp=multi->easy.next;
|
||||
while(easyp != &multi->easy) {
|
||||
singlesocket(multi, easyp);
|
||||
easyp = easyp->next;
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
singlesocket(multi, easy);
|
||||
easy = easy->next;
|
||||
}
|
||||
|
||||
/* or should we fall-through and do the timer-based stuff? */
|
||||
@@ -2194,35 +2201,35 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
/* If the pipeline is enabled, take the handle which is in the head of
|
||||
the pipeline. If we should write into the socket, take the send_pipe
|
||||
head. If we should read from the socket, take the recv_pipe head. */
|
||||
if(data->set.one_easy->easy_conn) {
|
||||
if(data->easy_conn) {
|
||||
if((ev_bitmask & CURL_POLL_OUT) &&
|
||||
data->set.one_easy->easy_conn->send_pipe &&
|
||||
data->set.one_easy->easy_conn->send_pipe->head)
|
||||
data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
|
||||
data->easy_conn->send_pipe &&
|
||||
data->easy_conn->send_pipe->head)
|
||||
data = data->easy_conn->send_pipe->head->ptr;
|
||||
else if((ev_bitmask & CURL_POLL_IN) &&
|
||||
data->set.one_easy->easy_conn->recv_pipe &&
|
||||
data->set.one_easy->easy_conn->recv_pipe->head)
|
||||
data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
|
||||
data->easy_conn->recv_pipe &&
|
||||
data->easy_conn->recv_pipe->head)
|
||||
data = data->easy_conn->recv_pipe->head->ptr;
|
||||
}
|
||||
|
||||
if(data->set.one_easy->easy_conn &&
|
||||
!(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
|
||||
if(data->easy_conn &&
|
||||
!(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
|
||||
/* set socket event bitmask if they're not locked */
|
||||
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
|
||||
data->easy_conn->cselect_bits = ev_bitmask;
|
||||
|
||||
do
|
||||
result = multi_runsingle(multi, now, data->set.one_easy);
|
||||
result = multi_runsingle(multi, now, data);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
|
||||
if(data->set.one_easy->easy_conn &&
|
||||
!(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
|
||||
if(data->easy_conn &&
|
||||
!(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
|
||||
/* clear the bitmask only if not locked */
|
||||
data->set.one_easy->easy_conn->cselect_bits = 0;
|
||||
data->easy_conn->cselect_bits = 0;
|
||||
|
||||
if(CURLM_OK >= result)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
singlesocket(multi, data->set.one_easy);
|
||||
singlesocket(multi, data);
|
||||
|
||||
/* Now we fall-through and do the timer-based stuff, since we don't want
|
||||
to force the user to have to deal with timeouts as long as at least
|
||||
@@ -2266,13 +2273,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
/* the first loop lap 'data' can be NULL */
|
||||
if(data) {
|
||||
do
|
||||
result = multi_runsingle(multi, now, data->set.one_easy);
|
||||
result = multi_runsingle(multi, now, data);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
|
||||
if(CURLM_OK >= result)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
singlesocket(multi, data->set.one_easy);
|
||||
singlesocket(multi, data);
|
||||
}
|
||||
|
||||
/* Check if there's one (more) expired timer to deal with! This function
|
||||
@@ -2472,7 +2479,7 @@ static int update_timer(struct Curl_multi *multi)
|
||||
void Curl_multi_set_easy_connection(struct SessionHandle *handle,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
handle->set.one_easy->easy_conn = conn;
|
||||
handle->easy_conn = conn;
|
||||
}
|
||||
|
||||
static bool isHandleAtHead(struct SessionHandle *handle,
|
||||
@@ -2560,8 +2567,8 @@ void Curl_expire(struct SessionHandle *data, long milli)
|
||||
struct timeval *nowp = &data->state.expiretime;
|
||||
int rc;
|
||||
|
||||
/* this is only interesting for multi-interface using libcurl, and only
|
||||
while there is still a multi interface struct remaining! */
|
||||
/* this is only interesting while there is still an associated multi struct
|
||||
remaining! */
|
||||
if(!multi)
|
||||
return;
|
||||
|
||||
@@ -2691,14 +2698,14 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
|
||||
|
||||
void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
||||
{
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *easy;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy != &multi->easy) {
|
||||
if(easy->state == CURLM_STATE_CONNECT_PEND) {
|
||||
easy=multi->easyp;
|
||||
while(easy) {
|
||||
if(easy->mstate == CURLM_STATE_CONNECT_PEND) {
|
||||
multistate(easy, CURLM_STATE_CONNECT);
|
||||
/* Make sure that the handle will be processed soonish. */
|
||||
Curl_expire(easy->easy_handle, 1);
|
||||
Curl_expire(easy, 1);
|
||||
}
|
||||
easy = easy->next; /* operate on next handle */
|
||||
}
|
||||
@@ -2708,16 +2715,16 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
||||
void Curl_multi_dump(const struct Curl_multi *multi_handle)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
struct SessionHandle *easy;
|
||||
int i;
|
||||
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
|
||||
multi->num_easy, multi->num_alive);
|
||||
for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
|
||||
if(easy->state < CURLM_STATE_COMPLETED) {
|
||||
for(easy=multi->easyp; easy; easy = easy->next) {
|
||||
if(easy->mstate < CURLM_STATE_COMPLETED) {
|
||||
/* only display handles that are not completed */
|
||||
fprintf(stderr, "handle %p, state %s, %d sockets\n",
|
||||
(void *)easy->easy_handle,
|
||||
statename[easy->state], easy->numsocks);
|
||||
(void *)easy,
|
||||
statename[easy->mstate], easy->numsocks);
|
||||
for(i=0; i < easy->numsocks; i++) {
|
||||
curl_socket_t s = easy->sockets[i];
|
||||
struct Curl_sh_entry *entry =
|
||||
|
@@ -59,27 +59,6 @@ typedef enum {
|
||||
#define GETSOCK_READABLE (0x00ff)
|
||||
#define GETSOCK_WRITABLE (0xff00)
|
||||
|
||||
struct Curl_one_easy {
|
||||
/* first, two fields for the linked list of these */
|
||||
struct Curl_one_easy *next;
|
||||
struct Curl_one_easy *prev;
|
||||
|
||||
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||
|
||||
CURLMstate state; /* the handle's state */
|
||||
CURLcode result; /* previous result */
|
||||
|
||||
struct Curl_message msg; /* A single posted message. */
|
||||
|
||||
/* Array with the plain socket numbers this handle takes care of, in no
|
||||
particular order. Note that all sockets are added to the sockhash, where
|
||||
the state etc are also kept. This array is mostly used to detect when a
|
||||
socket is to be removed from the hash. See singlesocket(). */
|
||||
curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
|
||||
int numsocks;
|
||||
};
|
||||
|
||||
/* This is the struct known as CURLM on the outside */
|
||||
struct Curl_multi {
|
||||
/* First a simple identifier to easier detect if a user mix up
|
||||
@@ -87,7 +66,8 @@ struct Curl_multi {
|
||||
long type;
|
||||
|
||||
/* We have a doubly-linked circular list with easy handles */
|
||||
struct Curl_one_easy easy;
|
||||
struct SessionHandle *easyp;
|
||||
struct SessionHandle *easylp; /* last node */
|
||||
|
||||
int num_easy; /* amount of entries in the linked list above. */
|
||||
int num_alive; /* amount of easy handles that are added but have not yet
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -60,6 +60,10 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
|
||||
unsigned char *md5sum, /* output */
|
||||
size_t md5len);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for NSS */
|
||||
#define curlssl_init Curl_nss_init
|
||||
#define curlssl_cleanup Curl_nss_cleanup
|
||||
|
@@ -6,6 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||
* Copyright (C) 2013, 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
|
||||
@@ -84,9 +85,10 @@ bool Curl_pipeline_penalized(struct SessionHandle *data,
|
||||
(curl_off_t)conn->chunk.datasize > chunk_penalty_size)
|
||||
penalized = TRUE;
|
||||
|
||||
infof(data, "Conn: %d (%p) Receive pipe weight: (%d/%d), penalized: %d\n",
|
||||
conn->connection_id, conn, recv_size,
|
||||
conn->chunk.datasize, penalized);
|
||||
infof(data, "Conn: %ld (%p) Receive pipe weight: (%" FORMAT_OFF_T
|
||||
"/%zu), penalized: %s\n",
|
||||
conn->connection_id, (void *)conn, recv_size,
|
||||
conn->chunk.datasize, penalized?"TRUE":"FALSE");
|
||||
return penalized;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -101,7 +103,7 @@ CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
|
||||
|
||||
pipeline = conn->send_pipe;
|
||||
|
||||
infof(conn->data, "Adding handle: conn: %p\n", conn);
|
||||
infof(conn->data, "Adding handle: conn: %p\n", (void *)conn);
|
||||
infof(conn->data, "Adding handle: send: %d\n", conn->send_pipe->size);
|
||||
infof(conn->data, "Adding handle: recv: %d\n", conn->recv_pipe->size);
|
||||
rc = Curl_addHandleToPipeline(handle, pipeline);
|
||||
@@ -111,7 +113,7 @@ CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
|
||||
conn->writechannel_inuse = FALSE; /* not in use yet */
|
||||
#ifdef DEBUGBUILD
|
||||
infof(conn->data, "%p is at send pipe head!\n",
|
||||
conn->send_pipe->head->ptr);
|
||||
(void *)conn->send_pipe->head->ptr);
|
||||
#endif
|
||||
Curl_expire(conn->send_pipe->head->ptr, 1);
|
||||
}
|
||||
@@ -144,7 +146,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle,
|
||||
conn->writechannel_inuse = FALSE; /* not used now */
|
||||
#ifdef DEBUGBUILD
|
||||
infof(conn->data, "%p is at send pipe head B!\n",
|
||||
conn->send_pipe->head->ptr);
|
||||
(void *)conn->send_pipe->head->ptr);
|
||||
#endif
|
||||
Curl_expire(conn->send_pipe->head->ptr, 1);
|
||||
}
|
||||
@@ -320,9 +322,9 @@ void print_pipeline(struct connectdata *conn)
|
||||
curr = cb_ptr->conn_list->head;
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
infof(data, "- Conn %d (%p) send_pipe: %d, recv_pipe: %d\n",
|
||||
infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n",
|
||||
conn->connection_id,
|
||||
conn,
|
||||
(void *)conn,
|
||||
conn->send_pipe->size,
|
||||
conn->recv_pipe->size);
|
||||
curr = curr->next;
|
||||
|
15
lib/pop3.c
15
lib/pop3.c
@@ -382,7 +382,7 @@ static void state(struct connectdata *conn, pop3state newstate)
|
||||
|
||||
if(pop3c->state != newstate)
|
||||
infof(conn->data, "POP3 %p state change from %s to %s\n",
|
||||
pop3c, names[pop3c->state], names[newstate]);
|
||||
(void *)pop3c, names[pop3c->state], names[newstate]);
|
||||
#endif
|
||||
|
||||
pop3c->state = newstate;
|
||||
@@ -405,7 +405,7 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
|
||||
pop3c->tls_supported = FALSE; /* Clear the TLS capability */
|
||||
|
||||
/* Send the CAPA command */
|
||||
result = Curl_pp_sendf(&pop3c->pp, "CAPA");
|
||||
result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA");
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_CAPA);
|
||||
@@ -424,7 +424,7 @@ static CURLcode pop3_perform_starttls(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* Send the STLS command */
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "STLS");
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS");
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_STARTTLS);
|
||||
@@ -693,7 +693,7 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
|
||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||
pop3->custom : command), pop3->id);
|
||||
else
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp,
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s",
|
||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||
pop3->custom : command));
|
||||
|
||||
@@ -714,7 +714,7 @@ static CURLcode pop3_perform_quit(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* Send the QUIT command */
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT");
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT");
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_QUIT);
|
||||
@@ -1020,7 +1020,7 @@ static CURLcode pop3_state_auth_digest_resp_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* Send an empty response */
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "");
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "");
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
@@ -1421,8 +1421,7 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
* connection phase.
|
||||
*
|
||||
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
||||
* phase is done when this function returns, or FALSE is not. When called as
|
||||
* a part of the easy interface, it will always be TRUE.
|
||||
* phase is done when this function returns, or FALSE if not.
|
||||
*/
|
||||
static CURLcode pop3_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -357,12 +357,21 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
||||
} /* Calculations end */
|
||||
|
||||
if(!(data->progress.flags & PGRS_HIDE)) {
|
||||
|
||||
/* progress meter has not been shut off */
|
||||
|
||||
if(data->set.fprogress) {
|
||||
/* There's a callback set, so we call that instead of writing
|
||||
anything ourselves. This really is the way to go. */
|
||||
if(data->set.fxferinfo) {
|
||||
/* There's a callback set, call that */
|
||||
result= data->set.fxferinfo(data->set.progress_client,
|
||||
data->progress.size_dl,
|
||||
data->progress.downloaded,
|
||||
data->progress.size_ul,
|
||||
data->progress.uploaded);
|
||||
if(result)
|
||||
failf(data, "Callback aborted");
|
||||
return result;
|
||||
}
|
||||
else if(data->set.fprogress) {
|
||||
/* The older deprecated callback is set, call that */
|
||||
result= data->set.fprogress(data->set.progress_client,
|
||||
(double)data->progress.size_dl,
|
||||
(double)data->progress.downloaded,
|
||||
|
46
lib/qssl.c
46
lib/qssl.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "sslgen.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
#include "select.h"
|
||||
#include "x509asn1.h"
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@@ -169,10 +170,7 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
|
||||
SSLHandle * h = connssl->handle;
|
||||
long timeout_ms;
|
||||
|
||||
h->exitPgm = NULL;
|
||||
|
||||
if(!data->set.ssl.verifyhost)
|
||||
h->exitPgm = Curl_qsossl_trap_cert;
|
||||
h->exitPgm = data->set.ssl.verifypeer? NULL: Curl_qsossl_trap_cert;
|
||||
|
||||
/* figure out how long time we should wait at maximum */
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
@@ -208,6 +206,8 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
|
||||
break;
|
||||
}
|
||||
|
||||
h->peerCert = NULL;
|
||||
h->peerCertLen = 0;
|
||||
rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT);
|
||||
|
||||
switch (rc) {
|
||||
@@ -238,6 +238,23 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
/* Verify host. */
|
||||
rc = Curl_verifyhost(conn, h->peerCert, h->peerCert + h->peerCertLen);
|
||||
if(rc != CURLE_OK)
|
||||
return rc;
|
||||
|
||||
/* Gather certificate info. */
|
||||
if(data->set.ssl.certinfo) {
|
||||
if(Curl_ssl_init_certinfo(data, 1))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(h->peerCert) {
|
||||
rc = Curl_extract_certinfo(conn, 0, h->peerCert,
|
||||
h->peerCert + h->peerCertLen);
|
||||
if(rc != CURLE_OK)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -257,20 +274,23 @@ CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
|
||||
if(rc == CURLE_OK) {
|
||||
rc = Curl_qsossl_create(conn, sockindex);
|
||||
|
||||
if(rc == CURLE_OK)
|
||||
if(rc == CURLE_OK) {
|
||||
rc = Curl_qsossl_handshake(conn, sockindex);
|
||||
else {
|
||||
if(rc != CURLE_OK)
|
||||
SSL_Destroy(connssl->handle);
|
||||
}
|
||||
}
|
||||
|
||||
if(rc == CURLE_OK) {
|
||||
conn->recv[sockindex] = qsossl_recv;
|
||||
conn->send[sockindex] = qsossl_send;
|
||||
connssl->state = ssl_connection_complete;
|
||||
}
|
||||
else {
|
||||
connssl->handle = NULL;
|
||||
connssl->use = FALSE;
|
||||
connssl->state = ssl_connection_none;
|
||||
}
|
||||
}
|
||||
if(rc == CURLE_OK) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = qsossl_recv;
|
||||
conn->send[sockindex] = qsossl_send;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@@ -668,7 +668,7 @@ static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
if(rtp_dataleft != 0 && rtp[0] == '$') {
|
||||
DEBUGF(infof(data, "RTP Rewinding %zu %s\n", rtp_dataleft,
|
||||
DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
|
||||
*readmore ? "(READMORE)" : ""));
|
||||
|
||||
/* Store the incomplete RTP packet for a "rewind" */
|
||||
|
@@ -10,7 +10,7 @@
|
||||
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
*
|
||||
* Copyright (C) 2001 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -498,7 +498,7 @@ static CURLcode choose_mech(struct connectdata *conn)
|
||||
/* We have no mechanism with a NULL name but keep this check */
|
||||
DEBUGASSERT(mech_name != NULL);
|
||||
if(mech_name == NULL) {
|
||||
infof(data, "Skipping mechanism with empty name (%p)\n", mech);
|
||||
infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech);
|
||||
continue;
|
||||
}
|
||||
tmp_allocation = realloc(conn->app_data, (*mech)->size);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -38,6 +38,8 @@ typedef unsigned long u_int32_t;
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <qsossl.h>
|
||||
#include <gskssl.h>
|
||||
#include <qsoasync.h>
|
||||
#include <gssapi.h>
|
||||
|
||||
extern int Curl_getaddrinfo_a(const char * nodename, const char * servname,
|
||||
@@ -68,6 +70,93 @@ extern char * Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp);
|
||||
#define SSL_Strerror Curl_SSL_Strerror_a
|
||||
|
||||
|
||||
/* GSKit wrappers. */
|
||||
|
||||
extern int Curl_gsk_environment_open(gsk_handle * my_env_handle);
|
||||
#define gsk_environment_open Curl_gsk_environment_open
|
||||
|
||||
extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
|
||||
gsk_handle * my_session_handle);
|
||||
#define gsk_secure_soc_open Curl_gsk_secure_soc_open
|
||||
|
||||
extern int Curl_gsk_environment_close(gsk_handle * my_env_handle);
|
||||
#define gsk_environment_close Curl_gsk_environment_close
|
||||
|
||||
extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
|
||||
#define gsk_secure_soc_close Curl_gsk_secure_soc_close
|
||||
|
||||
extern int Curl_gsk_environment_init(gsk_handle my_env_handle);
|
||||
#define gsk_environment_init Curl_gsk_environment_init
|
||||
|
||||
extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
|
||||
#define gsk_secure_soc_init Curl_gsk_secure_soc_init
|
||||
|
||||
extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
|
||||
GSK_BUF_ID bufID,
|
||||
const char * buffer,
|
||||
int bufSize);
|
||||
#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
|
||||
|
||||
extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
|
||||
GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE enumValue);
|
||||
#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
|
||||
|
||||
extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID,
|
||||
int numValue);
|
||||
#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
|
||||
|
||||
extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
|
||||
GSK_CALLBACK_ID callBackID,
|
||||
void * callBackAreaPtr);
|
||||
#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
|
||||
|
||||
extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
|
||||
GSK_BUF_ID bufID,
|
||||
const char * * buffer,
|
||||
int * bufSize);
|
||||
#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
|
||||
|
||||
extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
|
||||
GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE * enumValue);
|
||||
#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
|
||||
|
||||
extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID,
|
||||
int * numValue);
|
||||
#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
|
||||
|
||||
extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
|
||||
GSK_CERT_ID certID,
|
||||
const gsk_cert_data_elem * * certDataElem,
|
||||
int * certDataElementCount);
|
||||
#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
|
||||
|
||||
extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
|
||||
GSK_MISC_ID miscID);
|
||||
#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
|
||||
|
||||
extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
|
||||
char * readBuffer,
|
||||
int readBufSize, int * amtRead);
|
||||
#define gsk_secure_soc_read Curl_gsk_secure_soc_read
|
||||
|
||||
extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
|
||||
char * writeBuffer,
|
||||
int writeBufSize, int * amtWritten);
|
||||
#define gsk_secure_soc_write Curl_gsk_secure_soc_write
|
||||
|
||||
extern const char * Curl_gsk_strerror_a(int gsk_return_value);
|
||||
#define gsk_strerror Curl_gsk_strerror_a
|
||||
|
||||
extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
|
||||
int IOCompletionPort,
|
||||
Qso_OverlappedIO_t * communicationsArea);
|
||||
#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
|
||||
|
||||
|
||||
/* GSSAPI wrappers. */
|
||||
|
||||
extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
|
||||
@@ -107,6 +196,7 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
|
||||
gss_buffer_t output_token);
|
||||
#define gss_delete_sec_context Curl_gss_delete_sec_context_a
|
||||
|
||||
|
||||
/* LDAP wrappers. */
|
||||
|
||||
#define BerValue struct berval
|
||||
|
@@ -315,6 +315,7 @@ char * unix_path;
|
||||
#define d2i_PKCS12_fp D2I_PKCS12_FP
|
||||
#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT
|
||||
#define sk_num SK_NUM
|
||||
#define sk_pop SK_POP
|
||||
#define sk_pop_free SK_POP_FREE
|
||||
#define sk_value SK_VALUE
|
||||
|
||||
|
62
lib/slist.c
62
lib/slist.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -45,6 +45,38 @@ static struct curl_slist *slist_get_last(struct curl_slist *list)
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_slist_append_nodup() appends a string to the linked list. Rather than
|
||||
* copying the string in dynamic storage, it takes its ownership. The string
|
||||
* should have been malloc()ated. Curl_slist_append_nodup always returns
|
||||
* the address of the first record, so that you can use this function as an
|
||||
* initialization function as well as an append function.
|
||||
* If an error occurs, NULL is returned and the string argument is NOT
|
||||
* released.
|
||||
*/
|
||||
struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data)
|
||||
{
|
||||
struct curl_slist *last;
|
||||
struct curl_slist *new_item;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
|
||||
new_item = malloc(sizeof(struct curl_slist));
|
||||
if(!new_item)
|
||||
return NULL;
|
||||
|
||||
new_item->next = NULL;
|
||||
new_item->data = data;
|
||||
|
||||
/* if this is the first item, then new_item *is* the list */
|
||||
if(!list)
|
||||
return new_item;
|
||||
|
||||
last = slist_get_last(list);
|
||||
last->next = new_item;
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_slist_append() appends a string to the linked list. It always returns
|
||||
* the address of the first record, so that you can use this function as an
|
||||
@@ -55,32 +87,16 @@ static struct curl_slist *slist_get_last(struct curl_slist *list)
|
||||
struct curl_slist *curl_slist_append(struct curl_slist *list,
|
||||
const char *data)
|
||||
{
|
||||
struct curl_slist *last;
|
||||
struct curl_slist *new_item;
|
||||
|
||||
new_item = malloc(sizeof(struct curl_slist));
|
||||
if(new_item) {
|
||||
char *dupdata = strdup(data);
|
||||
if(dupdata) {
|
||||
new_item->next = NULL;
|
||||
new_item->data = dupdata;
|
||||
}
|
||||
else {
|
||||
free(new_item);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if(!dupdata)
|
||||
return NULL;
|
||||
|
||||
if(list) {
|
||||
last = slist_get_last(list);
|
||||
last->next = new_item;
|
||||
list = Curl_slist_append_nodup(list, dupdata);
|
||||
if(!list)
|
||||
free(dupdata);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/* if this is the first item, then new_item *is* the list */
|
||||
return new_item;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -29,5 +29,12 @@
|
||||
*/
|
||||
struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist);
|
||||
|
||||
/*
|
||||
* Curl_slist_append_nodup() takes ownership of the given string and appends
|
||||
* it to the list.
|
||||
*/
|
||||
struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list,
|
||||
char *data);
|
||||
|
||||
#endif /* HEADER_CURL_SLIST_H */
|
||||
|
||||
|
13
lib/smtp.c
13
lib/smtp.c
@@ -337,7 +337,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
|
||||
|
||||
if(smtpc->state != newstate)
|
||||
infof(conn->data, "SMTP %p state change from %s to %s\n",
|
||||
smtpc, names[smtpc->state], names[newstate]);
|
||||
(void *)smtpc, names[smtpc->state], names[newstate]);
|
||||
#endif
|
||||
|
||||
smtpc->state = newstate;
|
||||
@@ -403,7 +403,7 @@ static CURLcode smtp_perform_starttls(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* Send the STARTTLS command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS");
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_STARTTLS);
|
||||
@@ -664,7 +664,7 @@ static CURLcode smtp_perform_quit(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* Send the QUIT command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_QUIT);
|
||||
@@ -997,7 +997,7 @@ static CURLcode smtp_state_auth_digest_resp_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* Send an empty response */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "");
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
@@ -1159,7 +1159,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
||||
}
|
||||
|
||||
/* Send the DATA command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA");
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_DATA);
|
||||
@@ -1387,8 +1387,7 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
* the connection phase.
|
||||
*
|
||||
* The variable pointed to by 'done' will be TRUE if the protocol-layer
|
||||
* connect phase is done when this function returns, or FALSE if not. When
|
||||
* called as a part of the easy interface, it will always be TRUE.
|
||||
* connect phase is done when this function returns, or FALSE if not.
|
||||
*/
|
||||
static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
|
||||
* Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2013, 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
|
||||
@@ -260,8 +260,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
failf(data, "User was rejected by the SOCKS5 server (%u %u).",
|
||||
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
|
||||
Curl_safefree(service_name);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
@@ -269,8 +269,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
}
|
||||
|
||||
if(socksreq[1] != 1) { /* status / messgae type */
|
||||
failf(data, "Invalid SSPI authentication response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
failf(data, "Invalid SSPI authentication response type (%u %u).",
|
||||
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
|
||||
Curl_safefree(service_name);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
@@ -494,15 +494,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
failf(data, "User was rejected by the SOCKS5 server (%u %u).",
|
||||
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(socksreq[1] != 2) { /* status / message type */
|
||||
failf(data, "Invalid SSPI encryption response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
failf(data, "Invalid SSPI encryption response type (%u %u).",
|
||||
(unsigned int)socksreq[0], (unsigned int)socksreq[1]);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
@@ -549,8 +549,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
}
|
||||
|
||||
if(sspi_w_token[1].cbBuffer != 1) {
|
||||
failf(data, "Invalid SSPI encryption response length (%d).",
|
||||
sspi_w_token[1].cbBuffer);
|
||||
failf(data, "Invalid SSPI encryption response length (%lu).",
|
||||
(unsigned long)sspi_w_token[1].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
@@ -563,8 +563,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
}
|
||||
else {
|
||||
if(sspi_w_token[0].cbBuffer != 1) {
|
||||
failf(data, "Invalid SSPI encryption response length (%d).",
|
||||
sspi_w_token[0].cbBuffer);
|
||||
failf(data, "Invalid SSPI encryption response length (%lu).",
|
||||
(unsigned long)sspi_w_token[0].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
|
@@ -392,7 +392,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(sshc->state != nowstate) {
|
||||
infof(conn->data, "SFTP %p state change from %s to %s\n",
|
||||
sshc, names[sshc->state], names[nowstate]);
|
||||
(void *)sshc, names[sshc->state], names[nowstate]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
145
lib/sslgen.c
145
lib/sslgen.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -31,6 +31,8 @@
|
||||
Curl_ossl_ - prefix for OpenSSL ones
|
||||
Curl_gtls_ - prefix for GnuTLS ones
|
||||
Curl_nss_ - prefix for NSS ones
|
||||
Curl_qssl_ - prefix for QsoSSL ones
|
||||
Curl_gskit_ - prefix for GSKit ones
|
||||
Curl_polarssl_ - prefix for PolarSSL ones
|
||||
Curl_cyassl_ - prefix for CyaSSL ones
|
||||
Curl_schannel_ - prefix for Schannel SSPI ones
|
||||
@@ -45,6 +47,16 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#define SSLGEN_C
|
||||
#include "sslgen.h" /* generic SSL protos etc */
|
||||
@@ -52,17 +64,24 @@
|
||||
#include "gtls.h" /* GnuTLS versions */
|
||||
#include "nssg.h" /* NSS versions */
|
||||
#include "qssl.h" /* QSOSSL versions */
|
||||
#include "gskit.h" /* Global Secure ToolKit versions */
|
||||
#include "polarssl.h" /* PolarSSL versions */
|
||||
#include "axtls.h" /* axTLS versions */
|
||||
#include "cyassl.h" /* CyaSSL versions */
|
||||
#include "curl_schannel.h" /* Schannel SSPI version */
|
||||
#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */
|
||||
#include "slist.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
#include "url.h"
|
||||
#include "curl_memory.h"
|
||||
#include "progress.h"
|
||||
#include "share.h"
|
||||
#include "timeval.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -159,6 +178,62 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc)
|
||||
Curl_safefree(sslc->random_file);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_rand() returns a random unsigned integer, 32bit.
|
||||
*
|
||||
* This non-SSL function is put here only because this file is the only one
|
||||
* with knowledge of what the underlying SSL libraries provide in terms of
|
||||
* randomizers.
|
||||
*
|
||||
* NOTE: 'data' may be passed in as NULL when coming from external API without
|
||||
* easy handle!
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned int Curl_rand(struct SessionHandle *data)
|
||||
{
|
||||
unsigned int r;
|
||||
static unsigned int randseed;
|
||||
static bool seeded = FALSE;
|
||||
|
||||
#ifndef have_curlssl_random
|
||||
(void)data;
|
||||
#else
|
||||
if(data) {
|
||||
Curl_ssl_random(data, (unsigned char *)&r, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RANDOM_FILE
|
||||
if(!seeded) {
|
||||
/* if there's a random file to read a seed from, use it */
|
||||
int fd = open(RANDOM_FILE, O_RDONLY);
|
||||
if(fd > -1) {
|
||||
/* read random data into the randseed variable */
|
||||
ssize_t nread = read(fd, &randseed, sizeof(randseed));
|
||||
if(nread == sizeof(randseed))
|
||||
seeded = TRUE;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!seeded) {
|
||||
struct timeval now = curlx_tvnow();
|
||||
randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
|
||||
randseed = randseed * 1103515245 + 12345;
|
||||
randseed = randseed * 1103515245 + 12345;
|
||||
randseed = randseed * 1103515245 + 12345;
|
||||
seeded = TRUE;
|
||||
}
|
||||
|
||||
/* Return an unsigned 32-bit pseudo-random number. */
|
||||
r = randseed = randseed * 1103515245 + 12345;
|
||||
return (r << 16) | ((r >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
/* "global" init done? */
|
||||
@@ -518,17 +593,77 @@ void Curl_ssl_free_certinfo(struct SessionHandle *data)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_NSS) || \
|
||||
defined(USE_DARWINSSL)
|
||||
/* these functions are only used by some SSL backends */
|
||||
int Curl_ssl_init_certinfo(struct SessionHandle * data,
|
||||
int num)
|
||||
{
|
||||
struct curl_certinfo * ci = &data->info.certs;
|
||||
struct curl_slist * * table;
|
||||
|
||||
/* Initialize the certificate information structures. Return 0 if OK, else 1.
|
||||
*/
|
||||
Curl_ssl_free_certinfo(data);
|
||||
ci->num_of_certs = num;
|
||||
table = calloc((size_t) num, sizeof(struct curl_slist *));
|
||||
if(!table)
|
||||
return 1;
|
||||
|
||||
ci->certinfo = table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
|
||||
int certnum,
|
||||
const char *label,
|
||||
const char *value,
|
||||
size_t valuelen)
|
||||
{
|
||||
struct curl_certinfo * ci = &data->info.certs;
|
||||
char * output;
|
||||
struct curl_slist * nl;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
/* Add an information record for a particular certificate. */
|
||||
output = curl_maprintf("%s:%.*s", label, valuelen, value);
|
||||
if(!output)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
|
||||
if(!nl) {
|
||||
free(output);
|
||||
curl_slist_free_all(ci->certinfo[certnum]);
|
||||
res = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ci->certinfo[certnum] = nl;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a convenience function for push_certinfo_len that takes a zero
|
||||
* terminated value.
|
||||
*/
|
||||
CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data,
|
||||
int certnum,
|
||||
const char *label,
|
||||
const char *value)
|
||||
{
|
||||
size_t valuelen = strlen(value);
|
||||
|
||||
return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
|
||||
}
|
||||
|
||||
/* these functions are only provided by some SSL backends */
|
||||
|
||||
#ifdef have_curlssl_random
|
||||
void Curl_ssl_random(struct SessionHandle *data,
|
||||
unsigned char *entropy,
|
||||
size_t length)
|
||||
{
|
||||
curlssl_random(data, entropy, length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef have_curlssl_md5sum
|
||||
void Curl_ssl_md5sum(unsigned char *tmp, /* input */
|
||||
size_t tmplen,
|
||||
unsigned char *md5sum, /* output */
|
||||
@@ -536,6 +671,6 @@ void Curl_ssl_md5sum(unsigned char *tmp, /* input */
|
||||
{
|
||||
curlssl_md5sum(tmp, tmplen, md5sum, md5len);
|
||||
}
|
||||
#endif /* USE_SSLEAY || USE_GNUTLS || USE_NSS || USE_DARWINSSL */
|
||||
#endif
|
||||
|
||||
#endif /* USE_SSL */
|
||||
|
18
lib/sslgen.h
18
lib/sslgen.h
@@ -33,6 +33,8 @@ bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||
struct ssl_config_data* dest);
|
||||
void Curl_free_ssl_config(struct ssl_config_data* sslc);
|
||||
|
||||
unsigned int Curl_rand(struct SessionHandle *);
|
||||
|
||||
#ifdef USE_SSL
|
||||
int Curl_ssl_init(void);
|
||||
void Curl_ssl_cleanup(void);
|
||||
@@ -56,7 +58,16 @@ size_t Curl_ssl_version(char *buffer, size_t size);
|
||||
bool Curl_ssl_data_pending(const struct connectdata *conn,
|
||||
int connindex);
|
||||
int Curl_ssl_check_cxn(struct connectdata *conn);
|
||||
|
||||
/* Certificate information list handling. */
|
||||
|
||||
void Curl_ssl_free_certinfo(struct SessionHandle *data);
|
||||
int Curl_ssl_init_certinfo(struct SessionHandle * data, int num);
|
||||
CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum,
|
||||
const char * label, const char * value,
|
||||
size_t valuelen);
|
||||
CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
|
||||
const char * label, const char * value);
|
||||
|
||||
/* Functions to be used by SSL library adaptation functions */
|
||||
|
||||
@@ -83,6 +94,13 @@ void Curl_ssl_md5sum(unsigned char *tmp, /* input */
|
||||
|
||||
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
|
||||
|
||||
#ifdef have_curlssl_random
|
||||
#define HAVE_CURL_SSL_RANDOM
|
||||
#endif
|
||||
#ifdef have_curlssl_md5sum
|
||||
#define HAVE_CURL_SSL_MD5SUM
|
||||
#endif
|
||||
|
||||
#else
|
||||
/* When SSL support is not present, just define away these function calls */
|
||||
#define Curl_ssl_init() 1
|
||||
|
110
lib/ssluse.c
110
lib/ssluse.c
@@ -43,6 +43,7 @@
|
||||
#include "inet_pton.h"
|
||||
#include "ssluse.h"
|
||||
#include "connect.h"
|
||||
#include "slist.h"
|
||||
#include "strequal.h"
|
||||
#include "select.h"
|
||||
#include "sslgen.h"
|
||||
@@ -1790,60 +1791,6 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CURLcode push_certinfo_len(struct SessionHandle *data,
|
||||
int certnum,
|
||||
const char *label,
|
||||
const char *value,
|
||||
size_t valuelen)
|
||||
{
|
||||
struct curl_certinfo *ci = &data->info.certs;
|
||||
char *output;
|
||||
struct curl_slist *nl;
|
||||
CURLcode res = CURLE_OK;
|
||||
size_t labellen = strlen(label);
|
||||
size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
|
||||
|
||||
output = malloc(outlen);
|
||||
if(!output)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* sprintf the label and colon */
|
||||
snprintf(output, outlen, "%s:", label);
|
||||
|
||||
/* memcpy the value (it might not be zero terminated) */
|
||||
memcpy(&output[labellen+1], value, valuelen);
|
||||
|
||||
/* zero terminate the output */
|
||||
output[labellen + 1 + valuelen] = 0;
|
||||
|
||||
/* TODO: we should rather introduce an internal API that can do the
|
||||
equivalent of curl_slist_append but doesn't strdup() the given data as
|
||||
like in this place the extra malloc/free is totally pointless */
|
||||
nl = curl_slist_append(ci->certinfo[certnum], output);
|
||||
free(output);
|
||||
if(!nl) {
|
||||
curl_slist_free_all(ci->certinfo[certnum]);
|
||||
ci->certinfo[certnum] = NULL;
|
||||
res = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else
|
||||
ci->certinfo[certnum] = nl;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* this is a convenience function for push_certinfo_len that takes a zero
|
||||
terminated value */
|
||||
static CURLcode push_certinfo(struct SessionHandle *data,
|
||||
int certnum,
|
||||
const char *label,
|
||||
const char *value)
|
||||
{
|
||||
size_t valuelen = strlen(value);
|
||||
|
||||
return push_certinfo_len(data, certnum, label, value, valuelen);
|
||||
}
|
||||
|
||||
static void pubkey_show(struct SessionHandle *data,
|
||||
int num,
|
||||
const char *type,
|
||||
@@ -1867,7 +1814,7 @@ static void pubkey_show(struct SessionHandle *data,
|
||||
left -= 3;
|
||||
}
|
||||
infof(data, " %s: %s\n", namebuf, buffer);
|
||||
push_certinfo(data, num, namebuf, buffer);
|
||||
Curl_ssl_push_certinfo(data, num, namebuf, buffer);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
@@ -1936,7 +1883,7 @@ static int X509V3_ext(struct SessionHandle *data,
|
||||
}
|
||||
infof(data, " %s\n", buf);
|
||||
|
||||
push_certinfo(data, certnum, namebuf, buf);
|
||||
Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
|
||||
|
||||
BIO_free(bio_out);
|
||||
|
||||
@@ -1956,7 +1903,7 @@ static void X509_signature(struct SessionHandle *data,
|
||||
ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
|
||||
|
||||
infof(data, " Signature: %s\n", buf);
|
||||
push_certinfo(data, numcert, "Signature", buf);
|
||||
Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
|
||||
}
|
||||
|
||||
static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
|
||||
@@ -1972,30 +1919,13 @@ static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
|
||||
|
||||
infof(data, "%s\n", biomem->data);
|
||||
|
||||
push_certinfo_len(data, numcert, "Cert", biomem->data, biomem->length);
|
||||
Curl_ssl_push_certinfo_len(data, numcert,
|
||||
"Cert", biomem->data, biomem->length);
|
||||
|
||||
BIO_free(bio_out);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int init_certinfo(struct SessionHandle *data,
|
||||
int num)
|
||||
{
|
||||
struct curl_certinfo *ci = &data->info.certs;
|
||||
struct curl_slist **table;
|
||||
|
||||
Curl_ssl_free_certinfo(data);
|
||||
|
||||
ci->num_of_certs = num;
|
||||
table = calloc((size_t)num, sizeof(struct curl_slist *));
|
||||
if(!table)
|
||||
return 1;
|
||||
|
||||
ci->certinfo = table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This size was previously 512 which has been reported "too small" without
|
||||
* any specifics, so it was enlarged to allow more data to get shown uncut.
|
||||
@@ -2024,7 +1954,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
|
||||
}
|
||||
|
||||
numcerts = sk_X509_num(sk);
|
||||
if(init_certinfo(data, numcerts)) {
|
||||
if(Curl_ssl_init_certinfo(data, numcerts)) {
|
||||
free(bufp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -2049,16 +1979,16 @@ static CURLcode get_cert_chain(struct connectdata *conn,
|
||||
|
||||
(void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
|
||||
infof(data, "%2d Subject: %s\n", i, bufp);
|
||||
push_certinfo(data, i, "Subject", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Subject", bufp);
|
||||
|
||||
(void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
|
||||
infof(data, " Issuer: %s\n", bufp);
|
||||
push_certinfo(data, i, "Issuer", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
|
||||
|
||||
value = X509_get_version(x);
|
||||
infof(data, " Version: %lu (0x%lx)\n", value+1, value);
|
||||
snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
|
||||
push_certinfo(data, i, "Version", bufp); /* hex */
|
||||
Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
|
||||
|
||||
num=X509_get_serialNumber(x);
|
||||
if(num->length <= 4) {
|
||||
@@ -2087,30 +2017,30 @@ static CURLcode get_cert_chain(struct connectdata *conn,
|
||||
bufp[0]=0;
|
||||
}
|
||||
if(bufp[0])
|
||||
push_certinfo(data, i, "Serial Number", bufp); /* hex */
|
||||
Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
|
||||
|
||||
cinf = x->cert_info;
|
||||
|
||||
j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
|
||||
if(!j) {
|
||||
infof(data, " Signature Algorithm: %s\n", bufp);
|
||||
push_certinfo(data, i, "Signature Algorithm", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
|
||||
}
|
||||
|
||||
certdate = X509_get_notBefore(x);
|
||||
asn1_output(certdate, bufp, CERTBUFFERSIZE);
|
||||
infof(data, " Start date: %s\n", bufp);
|
||||
push_certinfo(data, i, "Start date", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Start date", bufp);
|
||||
|
||||
certdate = X509_get_notAfter(x);
|
||||
asn1_output(certdate, bufp, CERTBUFFERSIZE);
|
||||
infof(data, " Expire date: %s\n", bufp);
|
||||
push_certinfo(data, i, "Expire date", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
|
||||
|
||||
j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
|
||||
if(!j) {
|
||||
infof(data, " Public Key Algorithm: %s\n", bufp);
|
||||
push_certinfo(data, i, "Public Key Algorithm", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
|
||||
}
|
||||
|
||||
pubkey = X509_get_pubkey(x);
|
||||
@@ -2122,7 +2052,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
|
||||
infof(data, " RSA Public Key (%d bits)\n",
|
||||
BN_num_bits(pubkey->pkey.rsa->n));
|
||||
snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
|
||||
push_certinfo(data, i, "RSA Public Key", bufp);
|
||||
Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
|
||||
|
||||
print_pubkey_BN(rsa, n, i);
|
||||
print_pubkey_BN(rsa, e, i);
|
||||
@@ -2608,8 +2538,13 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
|
||||
*curlcode = CURLE_AGAIN;
|
||||
return -1;
|
||||
default:
|
||||
/* openssl/ssl.h says "look at error stack/return value/errno" */
|
||||
/* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
|
||||
value/errno" */
|
||||
/* http://www.openssl.org/docs/crypto/ERR_get_error.html */
|
||||
sslerror = ERR_get_error();
|
||||
if((nread < 0) || sslerror) {
|
||||
/* If the return code was negative or there actually is an error in the
|
||||
queue */
|
||||
failf(conn->data, "SSL read: %s, errno %d",
|
||||
ERR_error_string(sslerror, error_buffer),
|
||||
SOCKERRNO);
|
||||
@@ -2617,6 +2552,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -73,6 +73,10 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
|
||||
unsigned char *md5sum /* output */,
|
||||
size_t unused);
|
||||
|
||||
/* this backend provides these functions: */
|
||||
#define have_curlssl_random 1
|
||||
#define have_curlssl_md5sum 1
|
||||
|
||||
/* API setup for OpenSSL */
|
||||
#define curlssl_init Curl_ossl_init
|
||||
#define curlssl_cleanup Curl_ossl_cleanup
|
||||
|
122
lib/url.c
122
lib/url.c
@@ -124,6 +124,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out);
|
||||
#include "conncache.h"
|
||||
#include "multihandle.h"
|
||||
#include "pipeline.h"
|
||||
#include "dotdot.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -317,6 +318,13 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
|
||||
if(!result) {
|
||||
/* Store the username part of option if required */
|
||||
if(userp) {
|
||||
if(!user && option && option[0] == ':') {
|
||||
/* Allocate an empty string instead of returning NULL as user name */
|
||||
user = strdup("");
|
||||
if(!user)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_safefree(*userp);
|
||||
*userp = user;
|
||||
}
|
||||
@@ -1601,8 +1609,20 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
data->progress.callback = TRUE; /* no longer internal */
|
||||
else
|
||||
data->progress.callback = FALSE; /* NULL enforces internal */
|
||||
break;
|
||||
|
||||
case CURLOPT_XFERINFOFUNCTION:
|
||||
/*
|
||||
* Transfer info callback function
|
||||
*/
|
||||
data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
|
||||
if(data->set.fxferinfo)
|
||||
data->progress.callback = TRUE; /* no longer internal */
|
||||
else
|
||||
data->progress.callback = FALSE; /* NULL enforces internal */
|
||||
|
||||
break;
|
||||
|
||||
case CURLOPT_PROGRESSDATA:
|
||||
/*
|
||||
* Custom client data to pass to the progress callback
|
||||
@@ -1892,6 +1912,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
*/
|
||||
data->set.ssl.fsslctxp = va_arg(param, void *);
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT)
|
||||
case CURLOPT_CERTINFO:
|
||||
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||
break;
|
||||
@@ -2552,7 +2574,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
conn->handler->disconnect(conn, dead_connection);
|
||||
|
||||
/* unlink ourselves! */
|
||||
infof(data, "Closing connection %d\n", conn->connection_id);
|
||||
infof(data, "Closing connection %ld\n", conn->connection_id);
|
||||
Curl_conncache_remove_conn(data->state.conn_cache, conn);
|
||||
|
||||
#if defined(USE_LIBIDN)
|
||||
@@ -2583,7 +2605,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
}
|
||||
|
||||
conn_free(conn);
|
||||
data->state.current_conn = NULL;
|
||||
|
||||
Curl_speedinit(data);
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -2853,7 +2875,8 @@ ConnectionExists(struct SessionHandle *data,
|
||||
size_t best_pipe_len = max_pipe_len;
|
||||
struct curl_llist_element *curr;
|
||||
|
||||
infof(data, "Found bundle for host %s: %p\n", needle->host.name, bundle);
|
||||
infof(data, "Found bundle for host %s: %p\n",
|
||||
needle->host.name, (void *)bundle);
|
||||
|
||||
/* We can't pipe if we don't know anything about the server */
|
||||
if(canPipeline && !bundle->server_supports_pipelining) {
|
||||
@@ -2889,7 +2912,7 @@ ConnectionExists(struct SessionHandle *data,
|
||||
|
||||
if(dead) {
|
||||
check->data = data;
|
||||
infof(data, "Connection %d seems to be dead!\n",
|
||||
infof(data, "Connection %ld seems to be dead!\n",
|
||||
check->connection_id);
|
||||
|
||||
/* disconnect resources */
|
||||
@@ -3674,7 +3697,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
char protobuf[16];
|
||||
const char *protop;
|
||||
CURLcode result;
|
||||
bool fix_slash = FALSE;
|
||||
bool rebuild_url = FALSE;
|
||||
|
||||
*prot_missing = FALSE;
|
||||
|
||||
@@ -3825,14 +3848,14 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
memcpy(path+1, query, hostlen);
|
||||
|
||||
path[0]='/'; /* prepend the missing slash */
|
||||
fix_slash = TRUE;
|
||||
rebuild_url = TRUE;
|
||||
|
||||
*query=0; /* now cut off the hostname at the ? */
|
||||
}
|
||||
else if(!path[0]) {
|
||||
/* if there's no path set, use a single slash */
|
||||
strcpy(path, "/");
|
||||
fix_slash = TRUE;
|
||||
rebuild_url = TRUE;
|
||||
}
|
||||
|
||||
/* If the URL is malformatted (missing a '/' after hostname before path) we
|
||||
@@ -3845,32 +3868,52 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
is bigger than the path. Use +1 to move the zero byte too. */
|
||||
memmove(&path[1], path, strlen(path)+1);
|
||||
path[0] = '/';
|
||||
fix_slash = TRUE;
|
||||
rebuild_url = TRUE;
|
||||
}
|
||||
else {
|
||||
/* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
|
||||
char *newp = Curl_dedotdotify(path);
|
||||
if(!newp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(strcmp(newp, path)) {
|
||||
rebuild_url = TRUE;
|
||||
free(data->state.pathbuffer);
|
||||
data->state.pathbuffer = newp;
|
||||
data->state.path = newp;
|
||||
path = newp;
|
||||
}
|
||||
else
|
||||
free(newp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "fix_slash" means that the URL was malformatted so we need to generate an
|
||||
* updated version with the new slash inserted at the right place! We need
|
||||
* the corrected URL when communicating over HTTP proxy and we don't know at
|
||||
* this point if we're using a proxy or not.
|
||||
* "rebuild_url" means that one or more URL components have been modified so
|
||||
* we need to generate an updated full version. We need the corrected URL
|
||||
* when communicating over HTTP proxy and we don't know at this point if
|
||||
* we're using a proxy or not.
|
||||
*/
|
||||
if(fix_slash) {
|
||||
if(rebuild_url) {
|
||||
char *reurl;
|
||||
|
||||
size_t plen = strlen(path); /* new path, should be 1 byte longer than
|
||||
the original */
|
||||
size_t urllen = strlen(data->change.url); /* original URL length */
|
||||
|
||||
size_t prefixlen = strlen(conn->host.name);
|
||||
|
||||
if(!*prot_missing)
|
||||
prefixlen += strlen(protop) + strlen("://");
|
||||
|
||||
reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
|
||||
if(!reurl)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* copy the prefix */
|
||||
memcpy(reurl, data->change.url, urllen - (plen-1));
|
||||
memcpy(reurl, data->change.url, prefixlen);
|
||||
|
||||
/* append the trailing piece + zerobyte */
|
||||
memcpy(&reurl[urllen - (plen-1)], path, plen + 1);
|
||||
memcpy(&reurl[prefixlen], path, plen + 1);
|
||||
|
||||
/* possible free the old one */
|
||||
if(data->change.url_alloc) {
|
||||
@@ -3878,6 +3921,8 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
data->change.url_alloc = FALSE;
|
||||
}
|
||||
|
||||
infof(data, "Rebuilt URL to: %s\n", reurl);
|
||||
|
||||
data->change.url = reurl;
|
||||
data->change.url_alloc = TRUE; /* free this later */
|
||||
}
|
||||
@@ -4415,8 +4460,12 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
|
||||
/* Decode the user */
|
||||
newname = curl_easy_unescape(data, userp, 0, NULL);
|
||||
if(!newname)
|
||||
if(!newname) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(strlen(newname) < MAX_CURL_USER_LENGTH)
|
||||
strcpy(user, newname);
|
||||
@@ -4427,8 +4476,12 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
if(passwdp) {
|
||||
/* We have a password in the URL so decode it */
|
||||
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
|
||||
if(!newpasswd)
|
||||
if(!newpasswd) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
|
||||
strcpy(passwd, newpasswd);
|
||||
@@ -4439,8 +4492,12 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
if(optionsp) {
|
||||
/* We have an options list in the URL so decode it */
|
||||
char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
|
||||
if(!newoptions)
|
||||
if(!newoptions) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
|
||||
strcpy(options, newoptions);
|
||||
@@ -4540,16 +4597,21 @@ static CURLcode parse_login_details(const char *login, const size_t len,
|
||||
/* Allocate the password portion buffer */
|
||||
if(!result && passwdp && plen) {
|
||||
pbuf = malloc(plen + 1);
|
||||
if(!pbuf)
|
||||
if(!pbuf) {
|
||||
Curl_safefree(ubuf);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the options portion buffer */
|
||||
if(!result && optionsp && olen) {
|
||||
obuf = malloc(olen + 1);
|
||||
if(!obuf)
|
||||
if(!obuf) {
|
||||
Curl_safefree(pbuf);
|
||||
Curl_safefree(ubuf);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
/* Store the user portion if necessary */
|
||||
@@ -5274,7 +5336,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
|
||||
size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
|
||||
if(pipelen > 0) {
|
||||
infof(data, "Found connection %d, with requests in the pipe (%d)\n",
|
||||
infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
|
||||
conn_temp->connection_id, pipelen);
|
||||
|
||||
if(conn_temp->bundle->num_connections < max_host_connections &&
|
||||
@@ -5779,18 +5841,20 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
|
||||
*
|
||||
* TODO: A future libcurl should be able to work away this state.
|
||||
*
|
||||
* 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
|
||||
* DOING state there's more work to do!
|
||||
*/
|
||||
|
||||
CURLcode Curl_do_more(struct connectdata *conn, bool *completed)
|
||||
CURLcode Curl_do_more(struct connectdata *conn, int *complete)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
|
||||
*completed = FALSE;
|
||||
*complete = 0;
|
||||
|
||||
if(conn->handler->do_more)
|
||||
result = conn->handler->do_more(conn, completed);
|
||||
result = conn->handler->do_more(conn, complete);
|
||||
|
||||
if(!result && *completed)
|
||||
if(!result && (*complete == 1))
|
||||
/* do_complete must be called after the protocol-specific DO function */
|
||||
do_complete(conn);
|
||||
|
||||
@@ -5803,9 +5867,7 @@ CURLcode Curl_do_more(struct connectdata *conn, bool *completed)
|
||||
void Curl_reset_reqproto(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
if(data->state.proto.generic && data->state.current_conn != conn) {
|
||||
free(data->state.proto.generic);
|
||||
|
||||
Curl_safefree(data->state.proto.generic);
|
||||
data->state.proto.generic = NULL;
|
||||
}
|
||||
data->state.current_conn = conn;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -37,7 +37,7 @@ CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
|
||||
bool *async, bool *protocol_connect);
|
||||
CURLcode Curl_do(struct connectdata **, bool *done);
|
||||
CURLcode Curl_do_more(struct connectdata *, bool *completed);
|
||||
CURLcode Curl_do_more(struct connectdata *, int *completed);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
|
||||
CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
|
@@ -134,6 +134,10 @@
|
||||
#include <qsossl.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
#include <gskssl.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_AXTLS
|
||||
#include <axTLS/ssl.h>
|
||||
#undef malloc
|
||||
@@ -184,6 +188,7 @@
|
||||
#include "http.h"
|
||||
#include "rtsp.h"
|
||||
#include "wildcard.h"
|
||||
#include "multihandle.h"
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
# ifdef HAVE_GSSGNU
|
||||
@@ -322,6 +327,11 @@ struct ssl_connect_data {
|
||||
#ifdef USE_QSOSSL
|
||||
SSLHandle *handle;
|
||||
#endif /* USE_QSOSSL */
|
||||
#ifdef USE_GSKIT
|
||||
gsk_handle handle;
|
||||
int iocport;
|
||||
ssl_connect_state connecting_state;
|
||||
#endif
|
||||
#ifdef USE_AXTLS
|
||||
SSL_CTX* ssl_ctx;
|
||||
SSL* ssl;
|
||||
@@ -567,7 +577,7 @@ struct Curl_async {
|
||||
/* These function pointer types are here only to allow easier typecasting
|
||||
within the source when we need to cast between data pointers (such as NULL)
|
||||
and function pointers. */
|
||||
typedef CURLcode (*Curl_do_more_func)(struct connectdata *, bool *);
|
||||
typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
|
||||
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
|
||||
|
||||
|
||||
@@ -1285,8 +1295,6 @@ struct UrlState {
|
||||
struct POP3 *pop3;
|
||||
struct SMTP *smtp;
|
||||
} proto;
|
||||
/* current user of this SessionHandle instance, or NULL */
|
||||
struct connectdata *current_conn;
|
||||
|
||||
/* if true, force SSL connection retry (workaround for certain servers) */
|
||||
bool ssl_connect_retry;
|
||||
@@ -1319,7 +1327,7 @@ struct DynamicStatic {
|
||||
* the 'DynamicStatic' struct.
|
||||
* Character pointer fields point to dynamic storage, unless otherwise stated.
|
||||
*/
|
||||
struct Curl_one_easy; /* declared and used only in multi.c */
|
||||
|
||||
struct Curl_multi; /* declared and used only in multi.c */
|
||||
|
||||
enum dupstring {
|
||||
@@ -1419,7 +1427,8 @@ struct UserDefined {
|
||||
curl_read_callback fread_func; /* function that reads the input */
|
||||
int is_fread_set; /* boolean, has read callback been set to non-NULL? */
|
||||
int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */
|
||||
curl_progress_callback fprogress; /* function for progress information */
|
||||
curl_progress_callback fprogress; /* OLD and deprecated progress callback */
|
||||
curl_xferinfo_callback fxferinfo; /* progress callback */
|
||||
curl_debug_callback fdebug; /* function that write informational data */
|
||||
curl_ioctl_callback ioctl_func; /* function for I/O control */
|
||||
curl_sockopt_callback fsockopt; /* function for setting socket options */
|
||||
@@ -1481,12 +1490,6 @@ struct UserDefined {
|
||||
long buffer_size; /* size of receive buffer to use */
|
||||
void *private_data; /* application-private data */
|
||||
|
||||
struct Curl_one_easy *one_easy; /* When adding an easy handle to a multi
|
||||
handle, an internal 'Curl_one_easy'
|
||||
struct is created and this is a pointer
|
||||
to the particular struct associated with
|
||||
this SessionHandle */
|
||||
|
||||
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
|
||||
|
||||
long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
|
||||
@@ -1609,6 +1612,24 @@ struct Names {
|
||||
*/
|
||||
|
||||
struct SessionHandle {
|
||||
/* first, two fields for the linked list of these */
|
||||
struct SessionHandle *next;
|
||||
struct SessionHandle *prev;
|
||||
|
||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||
|
||||
CURLMstate mstate; /* the handle's state */
|
||||
CURLcode result; /* previous result */
|
||||
|
||||
struct Curl_message msg; /* A single posted message. */
|
||||
|
||||
/* Array with the plain socket numbers this handle takes care of, in no
|
||||
particular order. Note that all sockets are added to the sockhash, where
|
||||
the state etc are also kept. This array is mostly used to detect when a
|
||||
socket is to be removed from the hash. See singlesocket(). */
|
||||
curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
|
||||
int numsocks;
|
||||
|
||||
struct Names dns;
|
||||
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
|
||||
struct to which this "belongs" when used by
|
||||
@@ -1616,9 +1637,6 @@ struct SessionHandle {
|
||||
struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle
|
||||
struct to which this "belongs" when used
|
||||
by the easy interface */
|
||||
struct Curl_one_easy *multi_pos; /* if non-NULL, points to its position
|
||||
in multi controlling structure to assist
|
||||
in removal. */
|
||||
struct Curl_share *share; /* Share, handles global variable mutexing */
|
||||
struct SingleRequest req; /* Request-specific data */
|
||||
struct UserDefined set; /* values set by the libcurl user */
|
||||
|
1151
lib/x509asn1.c
Normal file
1151
lib/x509asn1.c
Normal file
File diff suppressed because it is too large
Load Diff
129
lib/x509asn1.h
Normal file
129
lib/x509asn1.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef HEADER_CURL_X509ASN1_H
|
||||
#define HEADER_CURL_X509ASN1_H
|
||||
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, 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_setup.h"
|
||||
|
||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT)
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
/*
|
||||
* Constants.
|
||||
*/
|
||||
|
||||
/* ASN.1 classes. */
|
||||
#define CURL_ASN1_UNIVERSAL 0
|
||||
#define CURL_ASN1_APPLICATION 1
|
||||
#define CURL_ASN1_CONTEXT_SPECIFIC 2
|
||||
#define CURL_ASN1_PRIVATE 3
|
||||
|
||||
/* ASN.1 types. */
|
||||
#define CURL_ASN1_BOOLEAN 1
|
||||
#define CURL_ASN1_INTEGER 2
|
||||
#define CURL_ASN1_BIT_STRING 3
|
||||
#define CURL_ASN1_OCTET_STRING 4
|
||||
#define CURL_ASN1_NULL 5
|
||||
#define CURL_ASN1_OBJECT_IDENTIFIER 6
|
||||
#define CURL_ASN1_OBJECT_DESCRIPTOR 7
|
||||
#define CURL_ASN1_INSTANCE_OF 8
|
||||
#define CURL_ASN1_REAL 9
|
||||
#define CURL_ASN1_ENUMERATED 10
|
||||
#define CURL_ASN1_EMBEDDED 11
|
||||
#define CURL_ASN1_UTF8_STRING 12
|
||||
#define CURL_ASN1_RELATIVE_OID 13
|
||||
#define CURL_ASN1_SEQUENCE 16
|
||||
#define CURL_ASN1_SET 17
|
||||
#define CURL_ASN1_NUMERIC_STRING 18
|
||||
#define CURL_ASN1_PRINTABLE_STRING 19
|
||||
#define CURL_ASN1_TELETEX_STRING 20
|
||||
#define CURL_ASN1_VIDEOTEX_STRING 21
|
||||
#define CURL_ASN1_IA5_STRING 22
|
||||
#define CURL_ASN1_UTC_TIME 23
|
||||
#define CURL_ASN1_GENERALIZED_TIME 24
|
||||
#define CURL_ASN1_GRAPHIC_STRING 25
|
||||
#define CURL_ASN1_VISIBLE_STRING 26
|
||||
#define CURL_ASN1_GENERAL_STRING 27
|
||||
#define CURL_ASN1_UNIVERSAL_STRING 28
|
||||
#define CURL_ASN1_CHARACTER_STRING 29
|
||||
#define CURL_ASN1_BMP_STRING 30
|
||||
|
||||
|
||||
/*
|
||||
* Types.
|
||||
*/
|
||||
|
||||
/* ASN.1 parsed element. */
|
||||
typedef struct {
|
||||
const char * beg; /* Pointer to element data. */
|
||||
const char * end; /* Pointer to 1st byte after element data. */
|
||||
unsigned char class; /* ASN.1 element class. */
|
||||
unsigned char tag; /* ASN.1 element tag. */
|
||||
bool constructed; /* Element is constructed. */
|
||||
} curl_asn1Element;
|
||||
|
||||
|
||||
/* ASN.1 OID table entry. */
|
||||
typedef struct {
|
||||
const char * numoid; /* Dotted-numeric OID. */
|
||||
const char * textoid; /* OID name. */
|
||||
} curl_OID;
|
||||
|
||||
|
||||
/* X509 certificate: RFC 5280. */
|
||||
typedef struct {
|
||||
curl_asn1Element certificate;
|
||||
curl_asn1Element version;
|
||||
curl_asn1Element serialNumber;
|
||||
curl_asn1Element signatureAlgorithm;
|
||||
curl_asn1Element signature;
|
||||
curl_asn1Element issuer;
|
||||
curl_asn1Element notBefore;
|
||||
curl_asn1Element notAfter;
|
||||
curl_asn1Element subject;
|
||||
curl_asn1Element subjectPublicKeyAlgorithm;
|
||||
curl_asn1Element subjectPublicKey;
|
||||
curl_asn1Element issuerUniqueID;
|
||||
curl_asn1Element subjectUniqueID;
|
||||
curl_asn1Element extensions;
|
||||
} curl_X509certificate;
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes.
|
||||
*/
|
||||
|
||||
const char * Curl_getASN1Element(curl_asn1Element * elem,
|
||||
const char * beg, const char * end);
|
||||
const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
|
||||
const char * Curl_DNtostr(curl_asn1Element * dn);
|
||||
void Curl_parseX509(curl_X509certificate * cert,
|
||||
const char * beg, const char * end);
|
||||
CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
|
||||
const char * beg, const char * end);
|
||||
CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
const char * beg, const char * end);
|
||||
|
||||
#endif /* USE_QSOSSL or USE_GSKIT */
|
||||
#endif /* HEADER_CURL_X509ASN1_H */
|
253
m4/xc-am-iface.m4
Normal file
253
m4/xc-am-iface.m4
Normal file
@@ -0,0 +1,253 @@
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
# xc-am-iface.m4
|
||||
#
|
||||
# Copyright (c) 2013 Daniel Stenberg <daniel@haxx.se>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# serial 1
|
||||
|
||||
|
||||
dnl _XC_AUTOMAKE_BODY
|
||||
dnl -------------------------------------------------
|
||||
dnl Private macro.
|
||||
dnl
|
||||
dnl This macro performs embedding of automake initialization
|
||||
dnl code into configure script. When automake version 1.14 or
|
||||
dnl newer is used at configure script generation time, this
|
||||
dnl results in 'subdir-objects' automake option being used.
|
||||
dnl When using automake versions older than 1.14 this option
|
||||
dnl is not used when generating configure script.
|
||||
dnl
|
||||
dnl Existence of automake _AM_PROG_CC_C_O m4 private macro
|
||||
dnl is used to differentiate automake version 1.14 from older
|
||||
dnl ones which lack this macro.
|
||||
|
||||
m4_define([_XC_AUTOMAKE_BODY],
|
||||
[dnl
|
||||
## --------------------------------------- ##
|
||||
## Start of automake initialization code ##
|
||||
## --------------------------------------- ##
|
||||
m4_ifdef([_AM_PROG_CC_C_O],
|
||||
[
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
],[
|
||||
AM_INIT_AUTOMAKE
|
||||
])dnl
|
||||
## ------------------------------------- ##
|
||||
## End of automake initialization code ##
|
||||
## ------------------------------------- ##
|
||||
dnl
|
||||
m4_define([$0], [])[]dnl
|
||||
])
|
||||
|
||||
|
||||
dnl XC_AUTOMAKE
|
||||
dnl -------------------------------------------------
|
||||
dnl Public macro.
|
||||
dnl
|
||||
dnl This macro embeds automake machinery into configure
|
||||
dnl script regardless of automake version used in order
|
||||
dnl to generate configure script.
|
||||
dnl
|
||||
dnl When using automake version 1.14 or newer, automake
|
||||
dnl initialization option 'subdir-objects' is used to
|
||||
dnl generate the configure script, otherwise this option
|
||||
dnl is not used.
|
||||
|
||||
AC_DEFUN([XC_AUTOMAKE],
|
||||
[dnl
|
||||
AC_PREREQ([2.50])dnl
|
||||
dnl
|
||||
AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl
|
||||
dnl
|
||||
_XC_AUTOMAKE_BODY
|
||||
dnl
|
||||
m4_ifdef([AM_INIT_AUTOMAKE],
|
||||
[m4_undefine([AM_INIT_AUTOMAKE])])dnl
|
||||
dnl
|
||||
m4_define([$0], [])[]dnl
|
||||
])
|
||||
|
||||
|
||||
dnl _XC_AMEND_DISTCLEAN_BODY ([LIST-OF-SUBDIRS])
|
||||
dnl -------------------------------------------------
|
||||
dnl Private macro.
|
||||
dnl
|
||||
dnl This macro performs shell code embedding into
|
||||
dnl configure script in order to modify distclean
|
||||
dnl and maintainer-clean targets of makefiles which
|
||||
dnl are located in given list of subdirs.
|
||||
dnl
|
||||
dnl See XC_AMEND_DISTCLEAN comments for details.
|
||||
|
||||
m4_define([_XC_AMEND_DISTCLEAN_BODY],
|
||||
[dnl
|
||||
## ---------------------------------- ##
|
||||
## Start of distclean amending code ##
|
||||
## ---------------------------------- ##
|
||||
|
||||
for xc_subdir in [$1]
|
||||
do
|
||||
|
||||
if test ! -f "$xc_subdir/Makefile"; then
|
||||
echo "$xc_msg_err $xc_subdir/Makefile file not found. $xc_msg_abrt" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fetch dependency tracking file list from Makefile include lines.
|
||||
|
||||
xc_inc_lines=`grep '^include .*(DEPDIR)' "$xc_subdir/Makefile" 2>/dev/null`
|
||||
xc_cnt_words=`echo "$xc_inc_lines" | wc -w | tr -d "$xc_space$xc_tab"`
|
||||
|
||||
# --disable-dependency-tracking might have been used, consequently
|
||||
# there is nothing to amend without a dependency tracking file list.
|
||||
|
||||
if test $xc_cnt_words -gt 0; then
|
||||
|
||||
AC_MSG_NOTICE([amending $xc_subdir/Makefile])
|
||||
|
||||
# Build Makefile specific patch hunk.
|
||||
|
||||
xc_p="$xc_subdir/xc_patch.tmp"
|
||||
|
||||
xc_rm_depfiles=`echo "$xc_inc_lines" \
|
||||
| $SED 's%include% -rm -f%' 2>/dev/null`
|
||||
|
||||
xc_dep_subdirs=`echo "$xc_inc_lines" \
|
||||
| $SED 's%include[[ ]][[ ]]*%%' 2>/dev/null \
|
||||
| $SED 's%(DEPDIR)/.*%(DEPDIR)%' 2>/dev/null \
|
||||
| sort | uniq`
|
||||
|
||||
echo "$xc_rm_depfiles" >$xc_p
|
||||
|
||||
for xc_dep_dir in $xc_dep_subdirs; do
|
||||
echo "${xc_tab}@xm_dep_cnt=\`ls $xc_dep_dir | wc -l 2>/dev/null\`; \\" >>$xc_p
|
||||
echo "${xc_tab}if test \$\$xm_dep_cnt -eq 0 && test -d $xc_dep_dir; then \\" >>$xc_p
|
||||
echo "${xc_tab} rm -rf $xc_dep_dir; \\" >>$xc_p
|
||||
echo "${xc_tab}fi" >>$xc_p
|
||||
done
|
||||
|
||||
# Build Makefile patching sed scripts.
|
||||
|
||||
xc_s1="$xc_subdir/xc_script_1.tmp"
|
||||
xc_s2="$xc_subdir/xc_script_2.tmp"
|
||||
xc_s3="$xc_subdir/xc_script_3.tmp"
|
||||
|
||||
cat >$xc_s1 <<\_EOT
|
||||
/^distclean[[ ]]*:/,/^[[^ ]][[^ ]]*:/{
|
||||
s/^.*(DEPDIR)/___xc_depdir_line___/
|
||||
}
|
||||
/^maintainer-clean[[ ]]*:/,/^[[^ ]][[^ ]]*:/{
|
||||
s/^.*(DEPDIR)/___xc_depdir_line___/
|
||||
}
|
||||
_EOT
|
||||
|
||||
cat >$xc_s2 <<\_EOT
|
||||
/___xc_depdir_line___$/{
|
||||
N
|
||||
/___xc_depdir_line___$/D
|
||||
}
|
||||
_EOT
|
||||
|
||||
cat >$xc_s3 <<_EOT
|
||||
/^___xc_depdir_line___/{
|
||||
r $xc_p
|
||||
d
|
||||
}
|
||||
_EOT
|
||||
|
||||
# Apply patch to Makefile and cleanup.
|
||||
|
||||
$SED -f "$xc_s1" "$xc_subdir/Makefile" >"$xc_subdir/Makefile.tmp1"
|
||||
$SED -f "$xc_s2" "$xc_subdir/Makefile.tmp1" >"$xc_subdir/Makefile.tmp2"
|
||||
$SED -f "$xc_s3" "$xc_subdir/Makefile.tmp2" >"$xc_subdir/Makefile.tmp3"
|
||||
|
||||
if test -f "$xc_subdir/Makefile.tmp3"; then
|
||||
mv -f "$xc_subdir/Makefile.tmp3" "$xc_subdir/Makefile"
|
||||
fi
|
||||
|
||||
test -f "$xc_subdir/Makefile.tmp1" && rm -f "$xc_subdir/Makefile.tmp1"
|
||||
test -f "$xc_subdir/Makefile.tmp2" && rm -f "$xc_subdir/Makefile.tmp2"
|
||||
test -f "$xc_subdir/Makefile.tmp3" && rm -f "$xc_subdir/Makefile.tmp3"
|
||||
|
||||
test -f "$xc_p" && rm -f "$xc_p"
|
||||
test -f "$xc_s1" && rm -f "$xc_s1"
|
||||
test -f "$xc_s2" && rm -f "$xc_s2"
|
||||
test -f "$xc_s3" && rm -f "$xc_s3"
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
## -------------------------------- ##
|
||||
## End of distclean amending code ##
|
||||
## -------------------------------- ##
|
||||
dnl
|
||||
m4_define([$0], [])[]dnl
|
||||
])
|
||||
|
||||
|
||||
dnl XC_AMEND_DISTCLEAN ([LIST-OF-SUBDIRS])
|
||||
dnl -------------------------------------------------
|
||||
dnl Public macro.
|
||||
dnl
|
||||
dnl This macro embeds shell code into configure script
|
||||
dnl that amends, at configure runtime, the distclean
|
||||
dnl and maintainer-clean targets of Makefiles located
|
||||
dnl in all subdirs given in the mandatory white-space
|
||||
dnl separated list argument.
|
||||
dnl
|
||||
dnl Embedding only takes place when using automake 1.14
|
||||
dnl or newer, otherwise amending code is not included
|
||||
dnl in generated configure script.
|
||||
dnl
|
||||
dnl distclean and maintainer-clean targets are modified
|
||||
dnl to avoid unconditional removal of dependency subdirs
|
||||
dnl which triggers distclean and maintainer-clean errors
|
||||
dnl when using automake 'subdir-objects' option along
|
||||
dnl with per-target objects and source files existing in
|
||||
dnl multiple subdirs used for different build targets.
|
||||
dnl
|
||||
dnl New behavior first removes each dependency tracking
|
||||
dnl file independently, and only removes each dependency
|
||||
dnl subdir when it finds out that it no longer holds any
|
||||
dnl dependency tracking file.
|
||||
dnl
|
||||
dnl When configure option --disable-dependency-tracking
|
||||
dnl is used no amending takes place given that there are
|
||||
dnl no dependency tracking files.
|
||||
|
||||
AC_DEFUN([XC_AMEND_DISTCLEAN],
|
||||
[dnl
|
||||
AC_PREREQ([2.50])dnl
|
||||
dnl
|
||||
m4_ifdef([_AC_OUTPUT_MAIN_LOOP],
|
||||
[m4_provide_if([_AC_OUTPUT_MAIN_LOOP], [],
|
||||
[m4_fatal([call to AC_OUTPUT needed before $0])])])dnl
|
||||
dnl
|
||||
m4_if([$#], [1], [], [m4_fatal([$0: wrong number of arguments])])dnl
|
||||
m4_if([$1], [], [m4_fatal([$0: missing argument])])dnl
|
||||
dnl
|
||||
AC_REQUIRE([XC_CONFIGURE_PREAMBLE])dnl
|
||||
dnl
|
||||
m4_ifdef([_AM_PROG_CC_C_O],
|
||||
[
|
||||
_XC_AMEND_DISTCLEAN_BODY([$1])
|
||||
])dnl
|
||||
m4_define([$0], [])[]dnl
|
||||
])
|
||||
|
@@ -59,7 +59,7 @@ dnl Private macro.
|
||||
|
||||
AC_DEFUN([_XC_PROG_CC], [
|
||||
AC_REQUIRE([_XC_PROG_CC_PREAMBLE])dnl
|
||||
AC_REQUIRE([XC_CHECK_USER_FLAGS])dnl
|
||||
AC_REQUIRE([XC_CHECK_BUILD_FLAGS])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AM_PROG_CC_C_O])dnl
|
||||
|
@@ -39,7 +39,7 @@ AC_DEFUN([_XC_CHECK_VAR_LIBS], [
|
||||
done
|
||||
if test $xc_bad_var_libs = yes; then
|
||||
AC_MSG_NOTICE([using LIBS: $LIBS])
|
||||
AC_MSG_NOTICE([LIBS error: LIBS may only be used to specify libraries (-lname).])
|
||||
AC_MSG_NOTICE([LIBS note: LIBS should only be used to specify libraries (-lname).])
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -68,7 +68,7 @@ AC_DEFUN([_XC_CHECK_VAR_LDFLAGS], [
|
||||
done
|
||||
if test $xc_bad_var_ldflags = yes; then
|
||||
AC_MSG_NOTICE([using LDFLAGS: $LDFLAGS])
|
||||
xc_bad_var_msg="LDFLAGS error: LDFLAGS may only be used to specify linker flags, not"
|
||||
xc_bad_var_msg="LDFLAGS note: LDFLAGS should only be used to specify linker flags, not"
|
||||
for xc_word in $LDFLAGS; do
|
||||
case "$xc_word" in
|
||||
-D*)
|
||||
@@ -110,7 +110,7 @@ AC_DEFUN([_XC_CHECK_VAR_CPPFLAGS], [
|
||||
done
|
||||
if test $xc_bad_var_cppflags = yes; then
|
||||
AC_MSG_NOTICE([using CPPFLAGS: $CPPFLAGS])
|
||||
xc_bad_var_msg="CPPFLAGS error: CPPFLAGS may only be used to specify C preprocessor flags, not"
|
||||
xc_bad_var_msg="CPPFLAGS note: CPPFLAGS should only be used to specify C preprocessor flags, not"
|
||||
for xc_word in $CPPFLAGS; do
|
||||
case "$xc_word" in
|
||||
-rpath*)
|
||||
@@ -158,7 +158,7 @@ AC_DEFUN([_XC_CHECK_VAR_CFLAGS], [
|
||||
done
|
||||
if test $xc_bad_var_cflags = yes; then
|
||||
AC_MSG_NOTICE([using CFLAGS: $CFLAGS])
|
||||
xc_bad_var_msg="CFLAGS error: CFLAGS may only be used to specify C compiler flags, not"
|
||||
xc_bad_var_msg="CFLAGS note: CFLAGS should only be used to specify C compiler flags, not"
|
||||
for xc_word in $CFLAGS; do
|
||||
case "$xc_word" in
|
||||
-D*)
|
||||
|
@@ -39,22 +39,24 @@ header files are thus altered during build process to use this pragma, in
|
||||
order to force libcurl enums of being type int (the pragma disposition in use
|
||||
before inclusion is restored before resuming the including unit compilation).
|
||||
|
||||
Three SSL implementations were present in libcurl. Nevertheless, none of them
|
||||
is available on OS/400. To support SSL on OS/400, a fourth implementation has
|
||||
been added (qssl.[ch]). There is no way to have different certificate stores
|
||||
for CAs and for personal/application certificates/key. More, the SSL context
|
||||
may be defined as an application identifier in the main certificate store,
|
||||
or as a keyring file. As a consequence, the meaning of some fields have been
|
||||
slightly altered:
|
||||
_ The "certificate identifier" is taken from CURLOPT_SSLCERT if defined, else
|
||||
from CURLOPT_CAINFO.
|
||||
_ The certificate identifier is then used as an application identifier in the
|
||||
main certificate store. If successful, this context is used.
|
||||
_ If the previous step failed, the certificate identifier is used as the file
|
||||
name of a keyring. CURLOPT_KEYPASSWD is used here as the keyring password.
|
||||
_ The default ca-bundle (CURLOPT_CAINFO) is set to the main certificate store's
|
||||
keyring file name: this allows to use the system global CAs by default. (In that
|
||||
case, the keyring password is safely recovered from the system... IBM dixit!)
|
||||
Two SSL implementations are available to libcurl on OS/400: QsoSSL which is
|
||||
obsolescent, does not support asynchronous I/O and only allows a single SSL
|
||||
context within a job, and GSKit that does not suffer from these limitations
|
||||
and is able to provide some information about the server certificate.
|
||||
Both implementations of SSL are working on "certificate stores" or keyrings,
|
||||
rather than individual certificate/key files. Certificate stores, as weel as
|
||||
"certificate labels" are managed by external IBM-defined applications.
|
||||
There are two ways to specify an SSL context:
|
||||
- By an application identifier.
|
||||
- By a keyring file pathname and (optionally) certificate label.
|
||||
To identify an SSL context by application identifier, use option
|
||||
SETOPT_SSLCERT to specify the application identifier.
|
||||
To address an SSL context by keyring and certificate label, use CURLOPT_CAINFO
|
||||
to set-up the keyring pathname, CURLOPT_SSLCERT to define the certificate label
|
||||
(omitting it will cause the default certificate in keyring to be used) and
|
||||
CURLOPT_KEYPASSWD to give the keyring password. If SSL is used without
|
||||
defining any of these options, the default (i.e.: system) keyring is used for
|
||||
server certificate validation.
|
||||
|
||||
Non-standard EBCDIC wrapper prototypes are defined in an additional header
|
||||
file: ccsidcurl.h. These should be self-explanatory to an OS/400-aware
|
||||
@@ -154,6 +156,14 @@ use:
|
||||
CURLINFO_PRIMARY_IP
|
||||
CURLINFO_RTSP_SESSION_ID
|
||||
CURLINFO_LOCAL_IP
|
||||
Likewise, the following options are followed by a struct curl_slist * * and a
|
||||
CCSID.
|
||||
CURLINFO_SSL_ENGINES
|
||||
CURLINFO_COOKIELIST
|
||||
Lists returned should be released with curl_slist_free_all() after use.
|
||||
Option CURLINFO_CERTINFO is followed by a struct curl_certinfo * * and a
|
||||
CCSID. Returned structures sould be free'ed using curl_certinfo_free_all() after
|
||||
use.
|
||||
Other options are processed like in curl_easy_getinfo().
|
||||
|
||||
Standard compilation environment does support neither autotools nor make;
|
||||
@@ -200,6 +210,8 @@ _ As a prerequisite, QADRT development environment must be installed.
|
||||
_ Install the curl source directory in IFS.
|
||||
_ Enter shell (QSH)
|
||||
_ Change current directory to the curl installation directory
|
||||
- If the SSL backend has to be changed, edit file lib/config-os400.h
|
||||
accordingly.
|
||||
_ Change current directory to ./packages/OS400
|
||||
_ Edit file iniscript.sh. You may want to change tunable configuration
|
||||
parameters, like debug info generation, optimisation level, listing option,
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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,7 @@
|
||||
|
||||
#include "curl.h"
|
||||
#include "mprintf.h"
|
||||
#include "slist.h"
|
||||
#include "urldata.h"
|
||||
#include "url.h"
|
||||
#include "getinfo.h"
|
||||
@@ -67,7 +68,7 @@ makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
|
||||
|
||||
ccsid &= 0xFFFF;
|
||||
|
||||
if (ccsid == NOCONV_CCSID)
|
||||
if(ccsid == NOCONV_CCSID)
|
||||
ccsid = ASCII_CCSID;
|
||||
|
||||
memset(buf, 0, ICONV_ID_SIZE);
|
||||
@@ -93,7 +94,7 @@ iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, unsigned int cstr)
|
||||
makeOS400IconvCode(tocode, ccsidout);
|
||||
memset(tocode + 13, 0, sizeof tocode - 13); /* Dest. code id format. */
|
||||
|
||||
if (cstr)
|
||||
if(cstr)
|
||||
fromcode[18] = '1'; /* Set null-terminator flag. */
|
||||
|
||||
return iconv_open(tocode, fromcode);
|
||||
@@ -117,23 +118,23 @@ convert(char * d, size_t dlen, int dccsid,
|
||||
*** Return the converted destination byte count, or -1 if error.
|
||||
**/
|
||||
|
||||
if (sccsid == 65535)
|
||||
if(sccsid == 65535)
|
||||
sccsid = ASCII_CCSID;
|
||||
|
||||
if (dccsid == 65535)
|
||||
if(dccsid == 65535)
|
||||
dccsid = ASCII_CCSID;
|
||||
|
||||
if (sccsid == dccsid) {
|
||||
if(sccsid == dccsid) {
|
||||
lslen = slen >= 0? slen: strlen(s) + 1;
|
||||
i = lslen < dlen? lslen: dlen;
|
||||
|
||||
if (s != d && i > 0)
|
||||
if(s != d && i > 0)
|
||||
memcpy(d, s, i);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
if (slen < 0) {
|
||||
if(slen < 0) {
|
||||
lslen = 0;
|
||||
cd = iconv_open_CCSID(dccsid, sccsid, 1);
|
||||
}
|
||||
@@ -142,12 +143,12 @@ convert(char * d, size_t dlen, int dccsid,
|
||||
cd = iconv_open_CCSID(dccsid, sccsid, 0);
|
||||
}
|
||||
|
||||
if (ICONV_OPEN_ERROR(cd))
|
||||
if(ICONV_OPEN_ERROR(cd))
|
||||
return -1;
|
||||
|
||||
i = dlen;
|
||||
|
||||
if ((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0)
|
||||
if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0)
|
||||
i = -1;
|
||||
else
|
||||
i -= dlen;
|
||||
@@ -174,24 +175,24 @@ dynconvert(int dccsid, const char * s, int slen, int sccsid)
|
||||
dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */
|
||||
d = malloc(dlen);
|
||||
|
||||
if (!d)
|
||||
if(!d)
|
||||
return (char *) NULL;
|
||||
|
||||
l = convert(d, dlen, dccsid, s, slen, sccsid);
|
||||
|
||||
if (l < 0) {
|
||||
if(l < 0) {
|
||||
free(d);
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
if (slen < 0) {
|
||||
if(slen < 0) {
|
||||
/* Need to null-terminate even when source length is given.
|
||||
Since destination code size is unknown, use a conversion to generate
|
||||
terminator. */
|
||||
|
||||
l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID);
|
||||
|
||||
if (l2 < 0) {
|
||||
if(l2 < 0) {
|
||||
free(d);
|
||||
return (char *) NULL;
|
||||
}
|
||||
@@ -199,10 +200,10 @@ dynconvert(int dccsid, const char * s, int slen, int sccsid)
|
||||
l += l2;
|
||||
}
|
||||
|
||||
if ((size_t) l < dlen) {
|
||||
if((size_t) l < dlen) {
|
||||
cp = realloc(d, l); /* Shorten to minimum needed. */
|
||||
|
||||
if (cp)
|
||||
if(cp)
|
||||
d = cp;
|
||||
}
|
||||
|
||||
@@ -210,6 +211,24 @@ dynconvert(int dccsid, const char * s, int slen, int sccsid)
|
||||
}
|
||||
|
||||
|
||||
static struct curl_slist *
|
||||
slist_convert(int dccsid, struct curl_slist * from, int sccsid)
|
||||
|
||||
{
|
||||
struct curl_slist * to = (struct curl_slist *) NULL;
|
||||
char * cp;
|
||||
|
||||
for (; from; from = from->next) {
|
||||
if(!(cp = dynconvert(dccsid, from->data, -1, sccsid))) {
|
||||
curl_slist_free_all(to);
|
||||
return (struct curl_slist *) NULL;
|
||||
}
|
||||
to = Curl_slist_append_nodup(to, cp);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
curl_version_ccsid(unsigned int ccsid)
|
||||
|
||||
@@ -220,16 +239,16 @@ curl_version_ccsid(unsigned int ccsid)
|
||||
|
||||
aversion = curl_version();
|
||||
|
||||
if (!aversion)
|
||||
if(!aversion)
|
||||
return aversion;
|
||||
|
||||
i = strlen(aversion) + 1;
|
||||
i *= MAX_CONV_EXPANSION;
|
||||
|
||||
if (!(eversion = Curl_thread_buffer(LK_CURL_VERSION, i)))
|
||||
if(!(eversion = Curl_thread_buffer(LK_CURL_VERSION, i)))
|
||||
return (char *) NULL;
|
||||
|
||||
if (convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0)
|
||||
if(convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0)
|
||||
return (char *) NULL;
|
||||
|
||||
return eversion;
|
||||
@@ -244,20 +263,20 @@ curl_easy_escape_ccsid(CURL * handle, const char * string, int length,
|
||||
char * s;
|
||||
char * d;
|
||||
|
||||
if (!string) {
|
||||
if(!string) {
|
||||
errno = EINVAL;
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
s = dynconvert(ASCII_CCSID, s, length? length: -1, sccsid);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return (char *) NULL;
|
||||
|
||||
d = curl_easy_escape(handle, s, 0);
|
||||
free(s);
|
||||
|
||||
if (!d)
|
||||
if(!d)
|
||||
return (char *) NULL;
|
||||
|
||||
s = dynconvert(dccsid, d, -1, ASCII_CCSID);
|
||||
@@ -275,26 +294,26 @@ curl_easy_unescape_ccsid(CURL * handle, const char * string, int length,
|
||||
char * s;
|
||||
char * d;
|
||||
|
||||
if (!string) {
|
||||
if(!string) {
|
||||
errno = EINVAL;
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
s = dynconvert(ASCII_CCSID, s, length? length: -1, sccsid);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return (char *) NULL;
|
||||
|
||||
d = curl_easy_unescape(handle, s, 0, outlength);
|
||||
free(s);
|
||||
|
||||
if (!d)
|
||||
if(!d)
|
||||
return (char *) NULL;
|
||||
|
||||
s = dynconvert(dccsid, d, -1, ASCII_CCSID);
|
||||
free(d);
|
||||
|
||||
if (s && outlength)
|
||||
if(s && outlength)
|
||||
*outlength = strlen(s);
|
||||
|
||||
return s;
|
||||
@@ -310,12 +329,12 @@ curl_slist_append_ccsid(struct curl_slist * list,
|
||||
|
||||
s = (char *) NULL;
|
||||
|
||||
if (!data)
|
||||
if(!data)
|
||||
return curl_slist_append(list, data);
|
||||
|
||||
s = dynconvert(ASCII_CCSID, data, -1, ccsid);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return (struct curl_slist *) NULL;
|
||||
|
||||
list = curl_slist_append(list, s);
|
||||
@@ -331,12 +350,12 @@ curl_getdate_ccsid(const char * p, const time_t * unused, unsigned int ccsid)
|
||||
char * s;
|
||||
time_t t;
|
||||
|
||||
if (!p)
|
||||
if(!p)
|
||||
return curl_getdate(p, unused);
|
||||
|
||||
s = dynconvert(ASCII_CCSID, p, -1, ccsid);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return (time_t) -1;
|
||||
|
||||
t = curl_getdate(s, unused);
|
||||
@@ -357,10 +376,10 @@ convert_version_info_string(const char * * stringp,
|
||||
`*bufp' and `*left' are updated accordingly.
|
||||
Return 0 if ok, else -1. */
|
||||
|
||||
if (*stringp) {
|
||||
if(*stringp) {
|
||||
l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID);
|
||||
|
||||
if (l <= 0)
|
||||
if(l <= 0)
|
||||
return -1;
|
||||
|
||||
*stringp = *bufp;
|
||||
@@ -393,12 +412,12 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
|
||||
|
||||
/* If caller has been compiled with a new version, error. */
|
||||
|
||||
if (stamp > CURLVERSION_NOW)
|
||||
if(stamp > CURLVERSION_NOW)
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
p = curl_version_info(stamp);
|
||||
|
||||
if (!p)
|
||||
if(!p)
|
||||
return p;
|
||||
|
||||
/* Measure thread space needed. */
|
||||
@@ -406,53 +425,53 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
|
||||
n = 0;
|
||||
nproto = 0;
|
||||
|
||||
if (p->protocols) {
|
||||
if(p->protocols) {
|
||||
while (p->protocols[nproto])
|
||||
n += strlen(p->protocols[nproto++]);
|
||||
|
||||
n += nproto++;
|
||||
}
|
||||
|
||||
if (p->version)
|
||||
if(p->version)
|
||||
n += strlen(p->version) + 1;
|
||||
|
||||
if (p->host)
|
||||
if(p->host)
|
||||
n += strlen(p->host) + 1;
|
||||
|
||||
if (p->ssl_version)
|
||||
if(p->ssl_version)
|
||||
n += strlen(p->ssl_version) + 1;
|
||||
|
||||
if (p->libz_version)
|
||||
if(p->libz_version)
|
||||
n += strlen(p->libz_version) + 1;
|
||||
|
||||
if (p->ares)
|
||||
if(p->ares)
|
||||
n += strlen(p->ares) + 1;
|
||||
|
||||
if (p->libidn)
|
||||
if(p->libidn)
|
||||
n += strlen(p->libidn) + 1;
|
||||
|
||||
if (p->libssh_version)
|
||||
if(p->libssh_version)
|
||||
n += strlen(p->libssh_version) + 1;
|
||||
|
||||
/* Allocate thread space. */
|
||||
|
||||
n *= MAX_CONV_EXPANSION;
|
||||
|
||||
if (nproto)
|
||||
if(nproto)
|
||||
n += nproto * sizeof(const char *);
|
||||
|
||||
cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n);
|
||||
id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO,
|
||||
sizeof *id);
|
||||
|
||||
if (!id || !cp)
|
||||
if(!id || !cp)
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
/* Copy data and convert strings. */
|
||||
|
||||
memcpy((char *) id, (char *) p, sizeof *p);
|
||||
|
||||
if (id->protocols) {
|
||||
if(id->protocols) {
|
||||
id->protocols = (const char * const *) cp;
|
||||
i = nproto * sizeof id->protocols[0];
|
||||
memcpy(cp, (char *) p->protocols, i);
|
||||
@@ -460,30 +479,30 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
|
||||
n -= i;
|
||||
|
||||
for (i = 0; id->protocols[i]; i++)
|
||||
if (convert_version_info_string(((const char * *) id->protocols) + i,
|
||||
if(convert_version_info_string(((const char * *) id->protocols) + i,
|
||||
&cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
}
|
||||
|
||||
if (convert_version_info_string(&id->version, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->version, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->host, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->host, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->ssl_version, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->ssl_version, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->libz_version, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->libz_version, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->ares, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->ares, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->libidn, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->libidn, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
if (convert_version_info_string(&id->libssh_version, &cp, &n, ccsid))
|
||||
if(convert_version_info_string(&id->libssh_version, &cp, &n, ccsid))
|
||||
return (curl_version_info_data *) NULL;
|
||||
|
||||
return id;
|
||||
@@ -500,15 +519,15 @@ curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid)
|
||||
|
||||
s = curl_easy_strerror(error);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return s;
|
||||
|
||||
i = MAX_CONV_EXPANSION * (strlen(s) + 1);
|
||||
|
||||
if (!(buf = Curl_thread_buffer(LK_EASY_STRERROR, i)))
|
||||
if(!(buf = Curl_thread_buffer(LK_EASY_STRERROR, i)))
|
||||
return (const char *) NULL;
|
||||
|
||||
if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
return (const char *) NULL;
|
||||
|
||||
return (const char *) buf;
|
||||
@@ -525,15 +544,15 @@ curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid)
|
||||
|
||||
s = curl_share_strerror(error);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return s;
|
||||
|
||||
i = MAX_CONV_EXPANSION * (strlen(s) + 1);
|
||||
|
||||
if (!(buf = Curl_thread_buffer(LK_SHARE_STRERROR, i)))
|
||||
if(!(buf = Curl_thread_buffer(LK_SHARE_STRERROR, i)))
|
||||
return (const char *) NULL;
|
||||
|
||||
if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
return (const char *) NULL;
|
||||
|
||||
return (const char *) buf;
|
||||
@@ -550,21 +569,39 @@ curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid)
|
||||
|
||||
s = curl_multi_strerror(error);
|
||||
|
||||
if (!s)
|
||||
if(!s)
|
||||
return s;
|
||||
|
||||
i = MAX_CONV_EXPANSION * (strlen(s) + 1);
|
||||
|
||||
if (!(buf = Curl_thread_buffer(LK_MULTI_STRERROR, i)))
|
||||
if(!(buf = Curl_thread_buffer(LK_MULTI_STRERROR, i)))
|
||||
return (const char *) NULL;
|
||||
|
||||
if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
|
||||
return (const char *) NULL;
|
||||
|
||||
return (const char *) buf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
curl_certinfo_free_all(struct curl_certinfo *info)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Free all memory used by certificate info. */
|
||||
if(info) {
|
||||
if(info->certinfo) {
|
||||
for (i = 0; i < info->num_of_certs; i++)
|
||||
curl_slist_free_all(info->certinfo[i]);
|
||||
free((char *) info->certinfo);
|
||||
}
|
||||
free((char *) info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CURLcode
|
||||
curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
|
||||
|
||||
@@ -577,6 +614,10 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
|
||||
char * s;
|
||||
char * d;
|
||||
struct SessionHandle * data;
|
||||
struct curl_slist * * slp;
|
||||
struct curl_certinfo * cipf;
|
||||
struct curl_certinfo * cipt;
|
||||
int i;
|
||||
|
||||
/* WARNING: unlike curl_easy_get_info(), the strings returned by this
|
||||
procedure have to be free'ed. */
|
||||
@@ -586,25 +627,66 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
|
||||
paramp = va_arg(arg, void *);
|
||||
ret = Curl_getinfo(data, info, paramp);
|
||||
|
||||
if (ret != CURLE_OK || ((int) info & CURLINFO_TYPEMASK) != CURLINFO_STRING) {
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
if(ret == CURLE_OK)
|
||||
switch ((int) info & CURLINFO_TYPEMASK) {
|
||||
|
||||
case CURLINFO_STRING:
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
va_end(arg);
|
||||
cpp = (char * *) paramp;
|
||||
s = *cpp;
|
||||
|
||||
if (!s)
|
||||
return ret;
|
||||
|
||||
if(s) {
|
||||
d = dynconvert(ccsid, s, -1, ASCII_CCSID);
|
||||
*cpp = d;
|
||||
|
||||
if (!d)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!d)
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CURLINFO_SLIST:
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
if(info == CURLINFO_CERTINFO) {
|
||||
cipf = *(struct curl_certinfo * *) paramp;
|
||||
if(cipf) {
|
||||
if(!(cipt = (struct curl_certinfo *) malloc(sizeof *cipt)))
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
else {
|
||||
cipt->certinfo = (struct curl_slist * *) calloc(cipf->num_of_certs +
|
||||
1, sizeof(struct curl_slist *));
|
||||
if(!cipt->certinfo)
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
else {
|
||||
cipt->num_of_certs = cipf->num_of_certs;
|
||||
for (i = 0; i < cipf->num_of_certs; i++)
|
||||
if(cipf->certinfo[i])
|
||||
if(!(cipt->certinfo[i] = slist_convert(ccsid,
|
||||
cipf->certinfo[i],
|
||||
ASCII_CCSID))) {
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ret != CURLE_OK) {
|
||||
curl_certinfo_free_all(cipt);
|
||||
cipt = (struct curl_certinfo *) NULL;
|
||||
}
|
||||
|
||||
*(struct curl_certinfo * *) paramp = cipt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
slp = (struct curl_slist * *) paramp;
|
||||
if(*slp)
|
||||
if(!(*slp = slist_convert(ccsid, *slp, ASCII_CCSID)))
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -634,9 +716,9 @@ Curl_formadd_release_local(struct curl_forms * forms, int nargs, int skip)
|
||||
|
||||
{
|
||||
while (nargs--)
|
||||
if (nargs != skip)
|
||||
if (Curl_is_formadd_string(forms[nargs].option))
|
||||
if (forms[nargs].value)
|
||||
if(nargs != skip)
|
||||
if(Curl_is_formadd_string(forms[nargs].option))
|
||||
if(forms[nargs].value)
|
||||
free((char *) forms[nargs].value);
|
||||
|
||||
free((char *) forms);
|
||||
@@ -652,35 +734,35 @@ Curl_formadd_convert(struct curl_forms * forms,
|
||||
char * cp;
|
||||
char * cp2;
|
||||
|
||||
if (formx < 0 || !forms[formx].value)
|
||||
if(formx < 0 || !forms[formx].value)
|
||||
return 0;
|
||||
|
||||
if (lengthx >= 0)
|
||||
if(lengthx >= 0)
|
||||
l = (int) forms[lengthx].value;
|
||||
else
|
||||
l = strlen(forms[formx].value) + 1;
|
||||
|
||||
cp = malloc(MAX_CONV_EXPANSION * l);
|
||||
|
||||
if (!cp)
|
||||
if(!cp)
|
||||
return -1;
|
||||
|
||||
l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID,
|
||||
forms[formx].value, l, ccsid);
|
||||
|
||||
if (l < 0) {
|
||||
if(l < 0) {
|
||||
free(cp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp2 = realloc(cp, l); /* Shorten buffer to the string size. */
|
||||
|
||||
if (cp2)
|
||||
if(cp2)
|
||||
cp = cp2;
|
||||
|
||||
forms[formx].value = cp;
|
||||
|
||||
if (lengthx >= 0)
|
||||
if(lengthx >= 0)
|
||||
forms[lengthx].value = (char *) l; /* Update to length after conversion. */
|
||||
|
||||
return l;
|
||||
@@ -729,7 +811,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
lformlen = ALLOC_GRANULE;
|
||||
lforms = malloc(lformlen * sizeof *lforms);
|
||||
|
||||
if (!lforms)
|
||||
if(!lforms)
|
||||
return CURL_FORMADD_MEMORY;
|
||||
|
||||
/* Process the arguments, copying them into local array, latching conversion
|
||||
@@ -747,11 +829,11 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
for (;;) {
|
||||
/* Make sure there is still room for an item in local array. */
|
||||
|
||||
if (nargs >= lformlen) {
|
||||
if(nargs >= lformlen) {
|
||||
lformlen += ALLOC_GRANULE;
|
||||
tforms = realloc(lforms, lformlen * sizeof *lforms);
|
||||
|
||||
if (!tforms) {
|
||||
if(!tforms) {
|
||||
result = CURL_FORMADD_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -761,7 +843,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
/* Get next option. */
|
||||
|
||||
if (forms) {
|
||||
if(forms) {
|
||||
/* Get option from array. */
|
||||
|
||||
option = forms->option;
|
||||
@@ -773,7 +855,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
option = va_arg(arg, CURLformoption);
|
||||
|
||||
if (option == CURLFORM_END)
|
||||
if(option == CURLFORM_END)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -786,7 +868,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
continue;
|
||||
|
||||
case CURLFORM_ARRAY:
|
||||
if (!forms) {
|
||||
if(!forms) {
|
||||
forms = va_arg(arg, struct curl_forms *);
|
||||
continue;
|
||||
}
|
||||
@@ -798,12 +880,12 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
option = CURLFORM_PTRNAME; /* Static for now. */
|
||||
|
||||
case CURLFORM_PTRNAME:
|
||||
if (namex >= 0)
|
||||
if(namex >= 0)
|
||||
result = CURL_FORMADD_OPTION_TWICE;
|
||||
|
||||
namex = nargs;
|
||||
|
||||
if (!forms) {
|
||||
if(!forms) {
|
||||
value = va_arg(arg, char *);
|
||||
nameccsid = (unsigned int) va_arg(arg, long);
|
||||
}
|
||||
@@ -815,12 +897,12 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
break;
|
||||
|
||||
case CURLFORM_COPYCONTENTS:
|
||||
if (contentx >= 0)
|
||||
if(contentx >= 0)
|
||||
result = CURL_FORMADD_OPTION_TWICE;
|
||||
|
||||
contentx = nargs;
|
||||
|
||||
if (!forms) {
|
||||
if(!forms) {
|
||||
value = va_arg(arg, char *);
|
||||
contentccsid = (unsigned int) va_arg(arg, long);
|
||||
}
|
||||
@@ -833,7 +915,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
case CURLFORM_PTRCONTENTS:
|
||||
case CURLFORM_BUFFERPTR:
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = va_arg(arg, char *); /* No conversion. */
|
||||
|
||||
break;
|
||||
@@ -841,7 +923,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
case CURLFORM_CONTENTSLENGTH:
|
||||
lengthx = nargs;
|
||||
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = (char *) va_arg(arg, long);
|
||||
|
||||
break;
|
||||
@@ -849,25 +931,25 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
case CURLFORM_NAMELENGTH:
|
||||
namelengthx = nargs;
|
||||
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = (char *) va_arg(arg, long);
|
||||
|
||||
break;
|
||||
|
||||
case CURLFORM_BUFFERLENGTH:
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = (char *) va_arg(arg, long);
|
||||
|
||||
break;
|
||||
|
||||
case CURLFORM_CONTENTHEADER:
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = (char *) va_arg(arg, struct curl_slist *);
|
||||
|
||||
break;
|
||||
|
||||
case CURLFORM_STREAM:
|
||||
if (!forms)
|
||||
if(!forms)
|
||||
value = (char *) va_arg(arg, void *);
|
||||
|
||||
break;
|
||||
@@ -875,7 +957,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
case CURLFORM_CONTENTTYPE:
|
||||
/* If a previous content has been encountered, convert it now. */
|
||||
|
||||
if (Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) {
|
||||
if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) {
|
||||
result = CURL_FORMADD_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -887,12 +969,12 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
default:
|
||||
/* Must be a convertible string. */
|
||||
|
||||
if (!Curl_is_formadd_string(option)) {
|
||||
if(!Curl_is_formadd_string(option)) {
|
||||
result = CURL_FORMADD_UNKNOWN_OPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!forms) {
|
||||
if(!forms) {
|
||||
value = va_arg(arg, char *);
|
||||
ccsid = (unsigned int) va_arg(arg, long);
|
||||
}
|
||||
@@ -905,7 +987,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
lforms[nargs].value = value;
|
||||
|
||||
if (Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) {
|
||||
if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) {
|
||||
result = CURL_FORMADD_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -913,7 +995,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
value = lforms[nargs].value;
|
||||
}
|
||||
|
||||
if (result != CURL_FORMADD_OK)
|
||||
if(result != CURL_FORMADD_OK)
|
||||
break;
|
||||
|
||||
lforms[nargs].value = value;
|
||||
@@ -924,15 +1006,15 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
/* Convert the name and the last content, now that we know their lengths. */
|
||||
|
||||
if (result == CURL_FORMADD_OK && namex >= 0) {
|
||||
if (Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0)
|
||||
if(result == CURL_FORMADD_OK && namex >= 0) {
|
||||
if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0)
|
||||
result = CURL_FORMADD_MEMORY;
|
||||
else
|
||||
lforms[namex].option = CURLFORM_COPYNAME; /* Force copy. */
|
||||
}
|
||||
|
||||
if (result == CURL_FORMADD_OK) {
|
||||
if (Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0)
|
||||
if(result == CURL_FORMADD_OK) {
|
||||
if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0)
|
||||
result = CURL_FORMADD_MEMORY;
|
||||
else
|
||||
contentx = -1;
|
||||
@@ -940,7 +1022,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
|
||||
|
||||
/* Do the formadd with our converted parameters. */
|
||||
|
||||
if (result == CURL_FORMADD_OK) {
|
||||
if(result == CURL_FORMADD_OK) {
|
||||
lforms[nargs].option = CURLFORM_END;
|
||||
result = curl_formadd(httppost, last_post,
|
||||
CURLFORM_ARRAY, lforms, CURLFORM_END);
|
||||
@@ -971,17 +1053,17 @@ Curl_formget_callback_ccsid(void * arg, const char * buf, size_t len)
|
||||
|
||||
p = (cfcdata *) arg;
|
||||
|
||||
if ((long) len <= 0)
|
||||
if((long) len <= 0)
|
||||
return (*p->append)(p->arg, buf, len);
|
||||
|
||||
b = malloc(MAX_CONV_EXPANSION * len);
|
||||
|
||||
if (!b)
|
||||
if(!b)
|
||||
return (size_t) -1;
|
||||
|
||||
l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID);
|
||||
|
||||
if (l < 0) {
|
||||
if(l < 0) {
|
||||
free(b);
|
||||
return (size_t) -1;
|
||||
}
|
||||
@@ -1026,13 +1108,13 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
the same message; but since threadsafeness is not handled here,
|
||||
this may occur (and we don't care!). */
|
||||
|
||||
if (testwarn) {
|
||||
if(testwarn) {
|
||||
testwarn = 0;
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
if ((int) STRING_LAST != (int) STRING_TLSAUTH_PASSWORD + 1)
|
||||
if((int) STRING_LAST != (int) STRING_TLSAUTH_PASSWORD + 1)
|
||||
#else
|
||||
if ((int) STRING_LAST != (int) STRING_MAIL_AUTH + 1)
|
||||
if((int) STRING_LAST != (int) STRING_MAIL_AUTH + 1)
|
||||
#endif
|
||||
curl_mfprintf(stderr,
|
||||
"*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n");
|
||||
@@ -1097,10 +1179,10 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
s = va_arg(arg, char *);
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
|
||||
if (s) {
|
||||
if(s) {
|
||||
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
|
||||
|
||||
if (!s) {
|
||||
if(!s) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -1108,7 +1190,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
|
||||
result = curl_easy_setopt(curl, tag, s);
|
||||
|
||||
if (s)
|
||||
if(s)
|
||||
free(s);
|
||||
|
||||
break;
|
||||
@@ -1122,16 +1204,16 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
|
||||
pfsize = data->set.postfieldsize;
|
||||
|
||||
if (!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
|
||||
if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
|
||||
result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pfsize == -1) {
|
||||
if(pfsize == -1) {
|
||||
/* Data is null-terminated. */
|
||||
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
|
||||
|
||||
if (!s) {
|
||||
if(!s) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -1139,7 +1221,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
else {
|
||||
/* Data length specified. */
|
||||
|
||||
if (pfsize < 0 || pfsize > SIZE_MAX) {
|
||||
if(pfsize < 0 || pfsize > SIZE_MAX) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
@@ -1147,19 +1229,19 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
len = pfsize;
|
||||
pfsize = len * MAX_CONV_EXPANSION;
|
||||
|
||||
if (pfsize > SIZE_MAX)
|
||||
if(pfsize > SIZE_MAX)
|
||||
pfsize = SIZE_MAX;
|
||||
|
||||
cp = malloc(pfsize);
|
||||
|
||||
if (!cp) {
|
||||
if(!cp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
|
||||
|
||||
if (pfsize < 0) {
|
||||
if(pfsize < 0) {
|
||||
free(cp);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -60,5 +60,6 @@ CURL_EXTERN int curl_formget_ccsid(struct curl_httppost * form, void * arg,
|
||||
curl_formget_callback append,
|
||||
unsigned int ccsid);
|
||||
CURL_EXTERN CURLcode curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...);
|
||||
CURL_EXTERN void curl_certinfo_free_all(struct curl_certinfo *info);
|
||||
|
||||
#endif
|
||||
|
@@ -498,6 +498,8 @@
|
||||
d c 87
|
||||
d CURLE_CHUNK_FAILED...
|
||||
d c 88
|
||||
d CURLE_NO_CONNECTION_AVAILABLE...
|
||||
d c 89
|
||||
*
|
||||
/if not defined(CURL_NO_OLDIES)
|
||||
d CURLE_URL_MALFORMAT_USER...
|
||||
@@ -859,6 +861,8 @@
|
||||
d c 20056
|
||||
d CURLOPT_PROGRESSDATA...
|
||||
d c 10057
|
||||
d CURLOPT_XFERINFODATA...
|
||||
d c 10057 PROGRESSDATA alias
|
||||
d CURLOPT_AUTOREFERER...
|
||||
d c 00058
|
||||
d CURLOPT_PROXYPORT...
|
||||
@@ -1154,6 +1158,10 @@
|
||||
d c 00216
|
||||
d CURLOPT_MAIL_AUTH...
|
||||
d c 10217
|
||||
d CURLOPT_SASL_IR...
|
||||
d c 00218
|
||||
d CURLOPT_XFERINFOFUNCTION...
|
||||
d c 20219
|
||||
*
|
||||
/if not defined(CURL_NO_OLDIES)
|
||||
d CURLOPT_SSLKEYPASSWD...
|
||||
@@ -1462,6 +1470,20 @@
|
||||
d c 10005
|
||||
d CURLMOPT_MAXCONNECTS...
|
||||
d c 00006
|
||||
d CURLMOPT_MAX_HOST_CONNECTIONS...
|
||||
d c 00007
|
||||
d CURLMOPT_MAX_PIPELINE_LENGTH...
|
||||
d c 00008
|
||||
d CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE...
|
||||
d c 30009
|
||||
d CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE...
|
||||
d c 30010
|
||||
d CURLMOPT_PIPELINING_SITE_BL...
|
||||
d c 10011
|
||||
d CURLMOPT_PIPELINING_SERVER_BL...
|
||||
d c 10012
|
||||
d CURLMOPT_MAX_TOTAL_CONNECTIONS...
|
||||
d c 00013
|
||||
*
|
||||
* Public API enums for RTSP requests.
|
||||
*
|
||||
@@ -1641,6 +1663,9 @@
|
||||
d s * based(######ptr######) procptr
|
||||
*
|
||||
d curl_progress_callback...
|
||||
d s * based(######ptr######) procptr
|
||||
*
|
||||
d curl_xferinfo_callback...
|
||||
d s * based(######ptr######) procptr
|
||||
*
|
||||
d curl_read_callback...
|
||||
@@ -2109,14 +2134,19 @@
|
||||
d code value like(CURLMcode)
|
||||
d ccsid 10u 0 value
|
||||
*
|
||||
* May be used for strings and structures.
|
||||
d curl_easy_getinfo_ccsid...
|
||||
d pr extproc('curl_easy_getinfo_ccsid')
|
||||
d like(CURLcode)
|
||||
d curl * value CURL *
|
||||
d info value like(CURLINFO)
|
||||
d stringarg * options(*nopass) char *
|
||||
d ptrarg * options(*nopass) char *
|
||||
d ccsid 10u 0 value options(*nopass)
|
||||
*
|
||||
d curl_certinfo_free_all...
|
||||
d pr extproc('curl_certinfo_free_all')
|
||||
d info * value
|
||||
*
|
||||
d curl_formadd_ccsid...
|
||||
d pr extproc('curl_formadd_ccsid')
|
||||
d like(CURLFORMcode)
|
||||
|
@@ -47,6 +47,7 @@ done
|
||||
|
||||
# Build in each directory.
|
||||
|
||||
for SUBDIR in include lib src tests
|
||||
# for SUBDIR in include lib src tests
|
||||
for SUBDIR in include lib src
|
||||
do "${SCRIPTDIR}/make-${SUBDIR}.sh"
|
||||
done
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -42,6 +42,11 @@
|
||||
#include <qsossl.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
#include <gskssl.h>
|
||||
#include <qsoasync.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
#include <gssapi.h>
|
||||
#endif
|
||||
@@ -451,6 +456,412 @@ Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
|
||||
#endif /* USE_QSOSSL */
|
||||
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
|
||||
/* ASCII wrappers for the GSKit procedures. */
|
||||
|
||||
/*
|
||||
* EBCDIC --> ASCII string mapping table.
|
||||
* Some strings returned by GSKit are dynamically allocated and automatically
|
||||
* released when closing the handle.
|
||||
* To provide the same functionality, we use a "private" handle that
|
||||
* holds the GSKit handle and a list of string mappings. This will allow
|
||||
* avoid conversion of already converted strings and releasing them upon
|
||||
* close time.
|
||||
*/
|
||||
|
||||
struct gskstrlist {
|
||||
struct gskstrlist * next;
|
||||
const char * ebcdicstr;
|
||||
const char * asciistr;
|
||||
};
|
||||
|
||||
struct Curl_gsk_descriptor {
|
||||
gsk_handle h;
|
||||
struct gskstrlist * strlist;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_open(gsk_handle * my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
gsk_handle h;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
p->strlist = (struct gskstrlist *) NULL;
|
||||
if((rc = gsk_environment_open(&p->h)) != GSK_OK)
|
||||
free(p);
|
||||
else
|
||||
*my_env_handle = (gsk_handle) p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
|
||||
gsk_handle * my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
gsk_handle h;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!my_session_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
|
||||
if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
p->strlist = (struct gskstrlist *) NULL;
|
||||
if((rc = gsk_secure_soc_open(h, &p->h)) != GSK_OK)
|
||||
free(p);
|
||||
else
|
||||
*my_session_handle = (gsk_handle) p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gsk_free_handle(struct Curl_gsk_descriptor * p)
|
||||
|
||||
{
|
||||
struct gskstrlist * q;
|
||||
|
||||
while ((q = p->strlist)) {
|
||||
p->strlist = q;
|
||||
free((void *) q->asciistr);
|
||||
free(q);
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_close(gsk_handle * my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!*my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) *my_env_handle;
|
||||
if ((rc = gsk_environment_close(&p->h)) == GSK_OK) {
|
||||
gsk_free_handle(p);
|
||||
*my_env_handle = (gsk_handle) NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!*my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) *my_session_handle;
|
||||
if ((rc = gsk_secure_soc_close(&p->h)) == GSK_OK) {
|
||||
gsk_free_handle(p);
|
||||
*my_session_handle = (gsk_handle) NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_init(gsk_handle my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_env_handle;
|
||||
return gsk_environment_init(p->h);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_init(p->h);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
|
||||
const char * buffer, int bufSize)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
char * ebcdicbuf;
|
||||
int rc;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!buffer)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(bufSize < 0)
|
||||
return GSK_ATTRIBUTE_INVALID_LENGTH;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
if(!bufSize)
|
||||
bufSize = strlen(buffer);
|
||||
if (!(ebcdicbuf = malloc(bufSize + 1)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
|
||||
ebcdicbuf[bufSize] = '\0';
|
||||
rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
|
||||
free(ebcdicbuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE enumValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_enum(p->h, enumID, enumValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID, int numValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_numeric_value(p->h, numID, numValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
|
||||
GSK_CALLBACK_ID callBackID,
|
||||
void * callBackAreaPtr)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cachestring(struct Curl_gsk_descriptor * p,
|
||||
const char * ebcdicbuf, int bufsize, const char * * buffer)
|
||||
|
||||
{
|
||||
int rc;
|
||||
char * asciibuf;
|
||||
struct gskstrlist * sp;
|
||||
|
||||
for (sp = p->strlist; sp; sp = sp->next)
|
||||
if(sp->ebcdicstr == ebcdicbuf)
|
||||
break;
|
||||
if(!sp) {
|
||||
if(!(sp = (struct gskstrlist *) malloc(sizeof *sp)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
if(!(asciibuf = malloc(bufsize + 1))) {
|
||||
free(sp);
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
|
||||
asciibuf[bufsize] = '\0';
|
||||
sp->ebcdicstr = ebcdicbuf;
|
||||
sp->asciistr = asciibuf;
|
||||
sp->next = p->strlist;
|
||||
p->strlist = sp;
|
||||
}
|
||||
*buffer = sp->asciistr;
|
||||
return GSK_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
|
||||
const char * * buffer, int * bufSize)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
const char * mybuf;
|
||||
int mylen;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!buffer || !bufSize)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
if ((rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen)) != GSK_OK)
|
||||
return rc;
|
||||
if((rc = cachestring(p, mybuf, mylen, buffer)) == GSK_OK)
|
||||
*bufSize = mylen;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE * enumValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_get_enum(p->h, enumID, enumValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID, int * numValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_get_numeric_value(p->h, numID, numValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
|
||||
GSK_CERT_ID certID,
|
||||
const gsk_cert_data_elem * * certDataElem,
|
||||
int * certDataElementCount)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
/* No need to convert code: text results are already in ASCII. */
|
||||
return gsk_attribute_get_cert_info(p->h, certID,
|
||||
certDataElem, certDataElementCount);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_misc(p->h, miscID);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
|
||||
int readBufSize, int * amtRead)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
|
||||
int writeBufSize, int * amtWritten)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
Curl_gsk_strerror_a(int gsk_return_value)
|
||||
|
||||
{
|
||||
int i;
|
||||
const char * cp;
|
||||
char * cp2;
|
||||
|
||||
cp = gsk_strerror(gsk_return_value);
|
||||
|
||||
if (!cp)
|
||||
return cp;
|
||||
|
||||
i = strlen(cp);
|
||||
|
||||
if (!(cp2 = Curl_thread_buffer(LK_GSK_ERROR, MAX_CONV_EXPANSION * i + 1)))
|
||||
return cp2;
|
||||
|
||||
i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
|
||||
cp2[i] = '\0';
|
||||
return cp2;
|
||||
}
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
|
||||
int IOCompletionPort,
|
||||
Qso_OverlappedIO_t * communicationsArea)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
|
||||
}
|
||||
|
||||
#endif /* USE_GSKIT */
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
|
||||
/* ASCII wrappers for the GSSAPI procedures. */
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, 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
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
typedef enum {
|
||||
LK_SSL_ERROR,
|
||||
LK_GSK_ERROR,
|
||||
LK_LDAP_ERROR,
|
||||
LK_CURL_VERSION,
|
||||
LK_VERSION_INFO,
|
||||
|
@@ -1,9 +1,36 @@
|
||||
EXTRA_DIST = \
|
||||
backup_gnv_curl_src.com \
|
||||
build_curl-config_script.com \
|
||||
build_gnv_curl.com \
|
||||
build_gnv_curl_pcsi_desc.com \
|
||||
build_gnv_curl_pcsi_text.com \
|
||||
build_gnv_curl_release_notes.com \
|
||||
build_libcurl_pc.com \
|
||||
build_vms.com \
|
||||
clean_gnv_curl.com \
|
||||
compare_curl_source.com \
|
||||
config_h.com \
|
||||
curl_crtl_init.c \
|
||||
curl_gnv_build_steps.txt \
|
||||
curl_release_note_start.txt \
|
||||
curl_startup.com \
|
||||
curlmsg.h \
|
||||
curlmsg.msg \
|
||||
curlmsg.sdl \
|
||||
curlmsg_vms.h \
|
||||
generate_config_vms_h_curl.com \
|
||||
readme
|
||||
generate_vax_transfer.com \
|
||||
gnv_conftest.c_first \
|
||||
gnv_curl_configure.sh \
|
||||
gnv_libcurl_symbols.opt \
|
||||
gnv_link_curl.com \
|
||||
macro32_exactcase.patch \
|
||||
make_gnv_curl_install.sh \
|
||||
make_pcsi_curl_kit_name.com \
|
||||
pcsi_gnv_curl_file_list.txt \
|
||||
pcsi_product_gnv_curl.com \
|
||||
readme \
|
||||
report_openssl_version.c \
|
||||
setup_gnv_curl_build.com \
|
||||
stage_curl_install.com \
|
||||
vms_eco_level.h
|
||||
|
132
packages/vms/backup_gnv_curl_src.com
Normal file
132
packages/vms/backup_gnv_curl_src.com
Normal file
@@ -0,0 +1,132 @@
|
||||
$! File: Backup_gnv_curl_src.com
|
||||
$!
|
||||
$! $Id$
|
||||
$!
|
||||
$! Procedure to create backup save sets for installing in a PCSI kit.
|
||||
$!
|
||||
$! To comply with most Open Source licenses, the source used for building
|
||||
$! a kit will be packaged with the distribution kit for the binary.
|
||||
$!
|
||||
$! Backup save sets are the only storage format that I can expect a
|
||||
$! VMS system to be able to extract ODS-5 filenames and directories.
|
||||
$!
|
||||
$! The make_pcsi_kit_name.com needs to be run before this procedure to
|
||||
$! properly name the files that will be created.
|
||||
$!
|
||||
$! This file is created from a template file for the purpose of making it
|
||||
$! easier to port Unix code, particularly open source code to VMS.
|
||||
$! Therefore permission is freely granted for any use.
|
||||
$!
|
||||
$! Copyright 2009, John Malmberg
|
||||
$!
|
||||
$! Permission to use, copy, modify, and/or distribute this software for any
|
||||
$! purpose with or without fee is hereby granted, provided that the above
|
||||
$! copyright notice and this permission notice appear in all copies.
|
||||
$!
|
||||
$! THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
$! WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
$! MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
$! ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
$! WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
$! ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
$! OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
$!
|
||||
$! 13-Jun-2009 J. Malmberg
|
||||
$!
|
||||
$!===========================================================================
|
||||
$!
|
||||
$! Save default
|
||||
$ default_dir = f$environment("DEFAULT")
|
||||
$!
|
||||
$ arch_type = f$getsyi("ARCH_NAME")
|
||||
$ arch_code = f$extract(0, 1, arch_type)
|
||||
$!
|
||||
$ if arch_code .nes. "V"
|
||||
$ then
|
||||
$ set proc/parse=extended
|
||||
$ endif
|
||||
$!
|
||||
$ ss_abort = 44
|
||||
$ status = ss_abort
|
||||
$!
|
||||
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
|
||||
$ if kit_name .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_BASH_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ producer = f$trnlnm("GNV_PCSI_PRODUCER")
|
||||
$ if producer .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_BASH_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ filename_base = f$trnlnm("GNV_PCSI_FILENAME_BASE")
|
||||
$ if filename_base .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_BASH_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$ node_swvers = f$getsyi("NODE_SWVERS")
|
||||
$ node_swvers_type = f$extract(0, 1, node_swvers)
|
||||
$ node_swvers_vers = f$extract(1, f$length(node_swvers), node_swvers)
|
||||
$ swvers_maj = f$element(0, ".", node_swvers_vers)
|
||||
$ node_swvers_min_update = f$element(1, ".", node_swvers_vers)
|
||||
$ swvers_min = f$element(0, "-", node_swvers_min_update)
|
||||
$ swvers_update = f$element(1, "-", node_swvers_min_update)
|
||||
$!
|
||||
$ if swvers_update .eqs. "-" then swvers_update = ""
|
||||
$!
|
||||
$ vms_vers = f$fao("!2ZB!2ZB!AS", 'swvers_maj', 'swvers_min', swvers_update)
|
||||
$!
|
||||
$!
|
||||
$!
|
||||
$! If available make an interchange save set
|
||||
$!-------------------------------------------
|
||||
$ interchange = ""
|
||||
$ if arch_code .eqs. "V"
|
||||
$ then
|
||||
$ interchange = "/interchange"
|
||||
$ endif
|
||||
$ if (swvers_maj .ges. "8") .and. (swvers_min .ges. 4)
|
||||
$ then
|
||||
$ interchange = "/interchange/noconvert"
|
||||
$ endif
|
||||
$!
|
||||
$!
|
||||
$! Move to the base directories
|
||||
$ set def [--]
|
||||
$!
|
||||
$! Put things back on error.
|
||||
$ on warning then goto all_exit
|
||||
$!
|
||||
$ current_default = f$environment("DEFAULT")
|
||||
$ my_dir = f$parse(current_default,,,"DIRECTORY") - "[" - "<" - ">" - "]"
|
||||
$!
|
||||
$ src_root = "src_root:"
|
||||
$ if f$trnlnm("src_root1") .nes. "" then src_root = "src_root1:"
|
||||
$ backup'interchange' 'src_root'[curl...]*.*;0 -
|
||||
'filename_base'_original_src.bck/sav
|
||||
$ status = $status
|
||||
$!
|
||||
$! There may be a VMS specific source kit
|
||||
$!-----------------------------------------
|
||||
$ vms_root = "vms_root:"
|
||||
$ if f$trnlnm("vms_root1") .nes. "" then vms_root = "vms_root1:"
|
||||
$ files_found = 0
|
||||
$ define/user sys$error nl:
|
||||
$ define/user sys$output nl:
|
||||
$ directory 'vms_root'[...]*.*;*/exc=*.dir
|
||||
$ if '$severity' .eq. 1 then files_found = 1
|
||||
$!
|
||||
$ if files_found .eq. 1
|
||||
$ then
|
||||
$ backup'interchange' 'vms_root'[curl...]*.*;0 -
|
||||
'filename_base'_vms_src.bck/sav
|
||||
$ status = $status
|
||||
$ endif
|
||||
$!
|
||||
$all_exit:
|
||||
$ set def 'default_dir'
|
||||
$ exit
|
288
packages/vms/build_curl-config_script.com
Normal file
288
packages/vms/build_curl-config_script.com
Normal file
@@ -0,0 +1,288 @@
|
||||
$! File: build_libcurl_pc.com
|
||||
$!
|
||||
$! $Id:$
|
||||
$!
|
||||
$! Build the curl-config file from the config_curl.in file
|
||||
$!
|
||||
$! Copyright 2013, John Malmberg
|
||||
$!
|
||||
$! Permission to use, copy, modify, and/or distribute this software for any
|
||||
$! purpose with or without fee is hereby granted, provided that the above
|
||||
$! copyright notice and this permission notice appear in all copies.
|
||||
$!
|
||||
$! THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
$! WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
$! MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
$! ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
$! WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
$! ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
$! OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
$!
|
||||
$!
|
||||
$! 15-Jun-2013 J. Malmberg
|
||||
$!
|
||||
$!===========================================================================
|
||||
$!
|
||||
$! Skip this if the curl-config. already exists.
|
||||
$ if f$search("[--]curl-config.") .nes. "" then goto all_exit
|
||||
$!
|
||||
$! Need to know the kit type.
|
||||
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
|
||||
$ if kit_name .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$!
|
||||
$! Parse the kit name into components.
|
||||
$!---------------------------------------
|
||||
$ producer = f$element(0, "-", kit_name)
|
||||
$ base = f$element(1, "-", kit_name)
|
||||
$ product = f$element(2, "-", kit_name)
|
||||
$ mmversion = f$element(3, "-", kit_name)
|
||||
$ majorver = f$extract(0, 3, mmversion)
|
||||
$ minorver = f$extract(3, 2, mmversion)
|
||||
$ updatepatch = f$element(4, "-", kit_name)
|
||||
$ if updatepatch .eqs. "-" then updatepatch = ""
|
||||
$!
|
||||
$! kit type of "D" means a daily build
|
||||
$ kit_type = f$edit(f$extract(0, 1, majorver), "upcase")
|
||||
$!
|
||||
$ cfg_file_in = "[--]curl-config.in"
|
||||
$!
|
||||
$ if f$search(cfg_file_in) .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "Can not find curl-config.in."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$ if (f$getsyi("HW_MODEL") .lt. 1024)
|
||||
$ then
|
||||
$ arch_name = "VAX"
|
||||
$ else
|
||||
$ arch_name = ""
|
||||
$ arch_name = arch_name + f$edit(f$getsyi("ARCH_NAME"), "UPCASE")
|
||||
$ if (arch_name .eqs. "") then arch_name = "UNK"
|
||||
$ endif
|
||||
$!
|
||||
$!
|
||||
$ curl_version = "0.0.0"
|
||||
$ open/read vf [--.include.curl]curlver.h
|
||||
$version_loop:
|
||||
$ read vf/end=version_loop_end line_in
|
||||
$ if line_in .eqs. "" then goto version_loop
|
||||
$ key = f$element(0, " ", line_in)
|
||||
$ if key .nes. "#define" then goto version_loop
|
||||
$ name = f$element(1, " ", line_in)
|
||||
$ if name .eqs. "LIBCURL_VERSION"
|
||||
$ then
|
||||
$ curl_version = f$element(2, " ", line_in) - """" - """"
|
||||
$ goto version_loop
|
||||
$ endif
|
||||
$ if name .eqs. "LIBCURL_VERSION_NUM"
|
||||
$ then
|
||||
$ version_num_hex = f$element(2, " ", line_in)
|
||||
$ version_num = version_num_hex - "0x"
|
||||
$ goto version_loop
|
||||
$ endif
|
||||
$version_loop_end:
|
||||
$ close vf
|
||||
$!
|
||||
$!
|
||||
$ create [--]curl-config.
|
||||
$ open/append pco [--]curl-config.
|
||||
$ open/read pci 'cfg_file_in'
|
||||
$cfg_file_loop:
|
||||
$ read pci/end=cfg_file_loop_end line_in
|
||||
$!
|
||||
$! blank lines
|
||||
$ if line_in .eqs. ""
|
||||
$ then
|
||||
$ write pco ""
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$!
|
||||
$! comment lines
|
||||
$ key = f$extract(0, 1, line_in)
|
||||
$ if key .eqs. "#"
|
||||
$ then
|
||||
$ write pco line_in
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$!
|
||||
$! No substitution line
|
||||
$ line_in_len = f$length(line_in)
|
||||
$ if f$locate("@", line_in) .ge. line_in_len
|
||||
$ then
|
||||
$ write pco line_in
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$!
|
||||
$ if f$locate("@prefix@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ if kit_type .nes. "D"
|
||||
$ then
|
||||
$ write pco "prefix=/usr"
|
||||
$ else
|
||||
$ write pco "prefix=/beta"
|
||||
$ endif
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@exec_prefix@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ if kit_type .nes. "D"
|
||||
$ then
|
||||
$ write pco "exec_prefix=/usr"
|
||||
$ else
|
||||
$ write pco "exec_prefix=/beta"
|
||||
$ endif
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("=@includedir@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco "includedir=$(prefix}/include"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("X@includedir@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " if test ""X$(prefix}/include""; then"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("I@includedir@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo "${CPPFLAG_CURL_STATICLIB}-I$(prefix}/include"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@CPPFLAG_CURL_STATICLIB@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco "cppflag_curl_staticlib=-DCURL_STATICLIB"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@ENABLE_SHARED@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo no"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@CURL_CA_BUNDLE@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo """""
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@CC@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo ""cc"""
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@SUPPORT_FEATURES@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ if arch_name .eqs. "VAX"
|
||||
$ then
|
||||
$ write pco " for feature in SSL libz NTLM ""; do"
|
||||
$ else
|
||||
$ write pco " for feature in SSL IPv6 libz NTLM ""; do"
|
||||
$ endif
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@SUPPORT_PROTOCOLS@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ proto1 = "DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS"
|
||||
$ proto2 = " LDAP LDAPS POP3 POP3S RTSP SMTP SMTPS TELNET TFTP"
|
||||
$ proto = proto1 + proto2
|
||||
$ write pco " for protocol in " + proto + "; do"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("libcurl @CURLVERSION@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo libcurl ''curl_version'"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("existing @CURLVERSION@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ line_start = -
|
||||
" echo ""requested version $checkfor is newer than existing"
|
||||
$ write pco "''line_start' ''curl_version'"""
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("`echo @versionnum@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " numuppercase=`echo ''version_num' | tr 'a-f' 'A-F'`"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate(" echo @versionnum@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " echo ''version_num'"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("X@libdir@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ part1 = " if test ""$(exec_prefix}/lib"" != ""X/usr/lib"""
|
||||
$ part2 = "-a ""X$(exec_prefix}/lib"" != ""X/usr/lib64""; then"
|
||||
$ write pco part1,part2
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("L@libdir@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " CURLLIBDIR=""$(exec_prefix}/lib """
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@REQUIRE_LIB_DEPS@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " if test "Xyes" = "Xyes"; then"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@LIBCURL_LIBS@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ if arch_name .eqs. "VAX"
|
||||
$ then
|
||||
$ write pco " echo ${CURLLIBDIR}-lssl -lcrypto -lz"
|
||||
$ else
|
||||
$ write pco " echo ${CURLLIBDIR}-lssl -lcrypto -lgssapi -lz"
|
||||
$ endif
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@ENABLE_STATIC@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ write pco " if test "Xyes" != "Xno" ; then"
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@LIBCURL_LIBS@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ part1 = " echo ${exec_prefix}/lib/libcurl.a"
|
||||
$ part2 = "-L/usr/lib -L/SSL_LIB"
|
||||
$ if arch_name .eqs. "VAX"
|
||||
$ then
|
||||
$ write pco "''part1' ''part2' -lssl -lcrypto -lz"
|
||||
$ else
|
||||
$ write pco "''part1' ''part2' -lssl -lcrypto -lgssapi -lz"
|
||||
$ endif
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$ if f$locate("@CONFIGURE_OPTIONS@", line_in) .lt line_in_len
|
||||
$ then
|
||||
$ if kit_type .nes. "D"
|
||||
$ then
|
||||
$ part1 = " echo "" '--prefix=/usr' '--exec-prefix=/usr' "
|
||||
$ else
|
||||
$ part1 = " echo "" '--prefix=/beta' '--exec_prefix=/beta' "
|
||||
$ endif
|
||||
$ if arch_name .eqs. "VAX"
|
||||
$ then
|
||||
$ part3 = ""
|
||||
$ else
|
||||
$ part3 = "'--with-gssapi' "
|
||||
$ endif
|
||||
$ part2 = "'--disable-dependency-tracking' '--disable-libtool-lock' "
|
||||
$ part4 = "'--disable-ntlm-wb' '--with-ca-path=gnv$curl_ca_path'"""
|
||||
$!
|
||||
$ write pco part1,part2,part3,part4
|
||||
$!
|
||||
$ goto cfg_file_loop
|
||||
$ endif
|
||||
$!
|
||||
$pc_file_loop_end:
|
||||
$ close pco
|
||||
$ close pci
|
||||
$!
|
||||
$all_exit:
|
||||
$ exit
|
38
packages/vms/build_gnv_curl.com
Normal file
38
packages/vms/build_gnv_curl.com
Normal file
@@ -0,0 +1,38 @@
|
||||
$! File: build_gnv_curl.com
|
||||
$!
|
||||
$! $Id$
|
||||
$!
|
||||
$! All in one build procedure
|
||||
$!
|
||||
$! Copyright 2009, John Malmberg
|
||||
$!
|
||||
$! Permission to use, copy, modify, and/or distribute this software for any
|
||||
$! purpose with or without fee is hereby granted, provided that the above
|
||||
$! copyright notice and this permission notice appear in all copies.
|
||||
$!
|
||||
$! THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
$! WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
$! MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
$! ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
$! WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
$! ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
$! OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
$!
|
||||
$!
|
||||
$! 11-Jun-2009 J. Malmberg
|
||||
$!-----------------------------------------------------------------------
|
||||
$!
|
||||
$ @setup_gnv_curl_build.com
|
||||
$!
|
||||
$ bash gnv_curl_configure.sh
|
||||
$!
|
||||
$ @clean_gnv_curl.com
|
||||
$!
|
||||
$ bash make_gnv_curl_install.sh
|
||||
$!
|
||||
$ @gnv_link_curl.com
|
||||
$!
|
||||
$ purge new_gnu:[*...]/log
|
||||
$!
|
||||
$!
|
||||
$exit
|
488
packages/vms/build_gnv_curl_pcsi_desc.com
Normal file
488
packages/vms/build_gnv_curl_pcsi_desc.com
Normal file
@@ -0,0 +1,488 @@
|
||||
$! File: Build_GNV_CURL_PCSI_DESC.COM
|
||||
$!
|
||||
$! $Id$
|
||||
$!
|
||||
$! Build the *.pcsi$text file in the following sections:
|
||||
$! Required software dependencies.
|
||||
$! install/upgrade/postinstall steps.
|
||||
$! 1. Duplicate filenames need an alias procedure. (N/A for curl)
|
||||
$! 2. ODS-5 filenames need an alias procedure. (N/A for curl)
|
||||
$! 3. Special alias links for executables (curl. -> curl.exe)
|
||||
$! if a lot, then an alias procedure is needed.
|
||||
$! 4. Rename the files to lowercase.
|
||||
$! Move Release Notes to destination
|
||||
$! Source kit option
|
||||
$! Create directory lines
|
||||
$! Add file lines for curl.
|
||||
$! Add Link alias procedure file (N/A for curl)
|
||||
$! Add [.SYS$STARTUP]curl_startup file
|
||||
$! Add Release notes file.
|
||||
$!
|
||||
$! The file PCSI_GNV_CURL_FILE_LIST.TXT is read in to get the files other
|
||||
$! than the release notes file and the source backup file.
|
||||
$!
|
||||
$! The PCSI system can really only handle ODS-2 format filenames and
|
||||
$! assumes that there is only one source directory. It also assumes that
|
||||
$! all destination files with the same name come from the same source file.
|
||||
$! Fortunately CURL does not trip most of these issues, so those steps
|
||||
$! above are marked N/A.
|
||||
$!
|
||||
$! A rename action section is needed to make sure that the files are
|
||||
$! created in the GNV$GNU: in the correct case, and to create the alias
|
||||
$! link [usr.bin]curl. for [usr.bin]curl.exe.
|
||||
$!
|
||||
$! Copyright 2009, John Malmberg
|
||||
$!
|
||||
$! Permission to use, copy, modify, and/or distribute this software for any
|
||||
$! purpose with or without fee is hereby granted, provided that the above
|
||||
$! copyright notice and this permission notice appear in all copies.
|
||||
$!
|
||||
$! THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
$! WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
$! MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
$! ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
$! WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
$! ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
$! OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
$!
|
||||
$!
|
||||
$! 15-Jun-2009 J. Malmberg
|
||||
$!
|
||||
$!===========================================================================
|
||||
$!
|
||||
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
|
||||
$ if kit_name .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ producer = f$trnlnm("GNV_PCSI_PRODUCER")
|
||||
$ if producer .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ filename_base = f$trnlnm("GNV_PCSI_FILENAME_BASE")
|
||||
$ if filename_base .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$!
|
||||
$! Parse the kit name into components.
|
||||
$!---------------------------------------
|
||||
$ producer = f$element(0, "-", kit_name)
|
||||
$ base = f$element(1, "-", kit_name)
|
||||
$ product = f$element(2, "-", kit_name)
|
||||
$ mmversion = f$element(3, "-", kit_name)
|
||||
$ majorver = f$extract(0, 3, mmversion)
|
||||
$ minorver = f$extract(3, 2, mmversion)
|
||||
$ updatepatch = f$element(4, "-", kit_name)
|
||||
$ if updatepatch .eqs. "-" then updatepatch = ""
|
||||
$!
|
||||
$! kit type of "D" means a daily build
|
||||
$ kit_type = f$edit(f$extract(0, 1, majorver), "upcase")
|
||||
$!
|
||||
$!
|
||||
$ product_line = "product ''producer' ''base' ''product'"
|
||||
$ if updatepatch .eqs. ""
|
||||
$ then
|
||||
$ product_name = " ''majorver'.''minorver'"
|
||||
$ else
|
||||
$ product_name = " ''majorver'.''minorver'-''updatepatch'"
|
||||
$ endif
|
||||
$ product_line = product_line + " ''product_name' full;"
|
||||
$!write sys$output product_line
|
||||
$!
|
||||
$!
|
||||
$!
|
||||
$! Create the file as a VMS text file.
|
||||
$!----------------------------------------
|
||||
$ base_file = kit_name
|
||||
$ create 'base_file'.pcsi$desc
|
||||
$!
|
||||
$!
|
||||
$! Start building file.
|
||||
$!----------------------
|
||||
$ open/append pdsc 'base_file'.pcsi$desc
|
||||
$!
|
||||
$ write pdsc product_line
|
||||
$!
|
||||
$! Required product dependencies.
|
||||
$!----------------------------------
|
||||
$ vmsprd = "DEC"
|
||||
$ if base .eqs. "I64VMS" then vmsprd = "HP"
|
||||
$!
|
||||
$ write pdsc " software ''vmsprd' ''base' VMS ;"
|
||||
$ arch_type = f$getsyi("ARCH_NAME")
|
||||
$ node_swvers = f$getsyi("node_swvers")
|
||||
$ vernum = f$extract(1, f$length(node_swvers), node_swvers)
|
||||
$ majver = f$element(0, ".", vernum)
|
||||
$ minverdash = f$element(1, ".", vernum)
|
||||
$ minver = f$element(0, "-", minverdash)
|
||||
$ dashver = f$element(1, "-", minverdash)
|
||||
$ if dashver .eqs. "-" then dashver = ""
|
||||
$ vmstag = majver + minver + dashver
|
||||
$ code = f$extract(0, 1, arch_type)
|
||||
$ arch_code = f$extract(0, 1, arch_type)
|
||||
$ write pdsc -
|
||||
" if (not <software ''vmsprd' ''base' VMS version minimum ''node_swvers'>) ;"
|
||||
$ write pdsc " error NEED_VMS''vmstag';"
|
||||
$ write pdsc " end if;"
|
||||
$!
|
||||
$write pdsc " software VMSPORTS ''base' ZLIB ;"
|
||||
$write pdsc -
|
||||
" if (not <software VMSPORTS ''base' ZLIB version minimum V1.2-8>) ;"
|
||||
$write pdsc " error NEED_ZLIB;"
|
||||
$write pdsc " end if;"
|
||||
$!
|
||||
$!
|
||||
$!
|
||||
$! install/upgrade/postinstall steps.
|
||||
$!-----------------------------------
|
||||
$! 1. Duplicate filenames need an alias procedure. (N/A for curl)
|
||||
$! 2. ODS-5 filenames need an alias procedure. (N/A for curl)
|
||||
$! 3. Special alias links for executables (curl. -> curl.exe)
|
||||
$! if a lot, then an alias procedure is needed.
|
||||
$! 4. Rename the files to lowercase.
|
||||
$!
|
||||
$!
|
||||
$! Alias links needed.
|
||||
$!-------------------------
|
||||
$ add_alias_lines = ""
|
||||
$ rem_alias_lines = ""
|
||||
$ line_out = ""
|
||||
$!
|
||||
$! Read through the file list to set up aliases and rename commands.
|
||||
$!---------------------------------------------------------------------
|
||||
$ open/read flst pcsi_gnv_curl_file_list.txt
|
||||
$!
|
||||
$inst_alias_loop:
|
||||
$ read/end=inst_alias_loop_end flst line_in
|
||||
$ line_in = f$edit(line_in,"compress,trim,uncomment")
|
||||
$ if line_in .eqs. "" then goto inst_alias_loop
|
||||
$ pathname = f$element(0, " ", line_in)
|
||||
$ linkflag = f$element(1, " ", line_in)
|
||||
|
||||
$ if linkflag .nes. "->" then goto inst_alias_write
|
||||
$!
|
||||
$ linktarget = f$element(2, " ", line_in)
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ old_start = f$locate("[gnv.usr", pathname)
|
||||
$ if old_start .lt. f$length(pathname)
|
||||
$ then
|
||||
$ pathname = "[gnv.beta" + pathname - "[gnv.usr"
|
||||
$ linktarget = "[gnv.beta" + linktarget - "[gnv.usr"
|
||||
$ endif
|
||||
$ endif
|
||||
$ nlink = "pcsi$destination:" + pathname
|
||||
$ ntarg = "pcsi$destination:" + linktarget
|
||||
$ new_add_alias_line = -
|
||||
"""if f$search(""""''nlink'"""") .eqs. """""""" then" + -
|
||||
" set file/enter=''nlink' ''ntarg'"""
|
||||
$ if add_alias_lines .nes. ""
|
||||
$ then
|
||||
$ add_alias_lines = add_alias_lines + "," + new_add_alias_line
|
||||
$ else
|
||||
$ add_alias_lines = new_add_alias_line
|
||||
$ endif
|
||||
$!
|
||||
$ new_rem_alias_line = -
|
||||
"""if f$search(""""''nlink'"""") .nes. """""""" then" + -
|
||||
" set file/remove ''nlink';"""
|
||||
$ if rem_alias_lines .nes. ""
|
||||
$ then
|
||||
$ rem_alias_lines = rem_alias_lines + "," + new_rem_alias_line
|
||||
$ else
|
||||
$ rem_alias_lines = new_rem_alias_line
|
||||
$ endif
|
||||
$!
|
||||
$ goto inst_alias_loop
|
||||
$!
|
||||
$inst_alias_write:
|
||||
$!
|
||||
$! execute install / remove
|
||||
$ write pdsc " execute install ("
|
||||
$! add aliases
|
||||
$ i = 0
|
||||
$ex_ins_loop:
|
||||
$ line = f$element(i, ",", add_alias_lines)
|
||||
$ i = i + 1
|
||||
$ if line .eqs. "" then goto ex_ins_loop
|
||||
$ if line .eqs. "," then goto ex_ins_loop_end
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ line_out = line
|
||||
$ goto ex_ins_loop
|
||||
$ex_ins_loop_end:
|
||||
$ write pdsc line_out
|
||||
$ line_out = ""
|
||||
$ write pdsc " )"
|
||||
$ write pdsc " remove ("
|
||||
$! remove aliases
|
||||
$ i = 0
|
||||
$ex_rem_loop:
|
||||
$ line = f$element(i, ",", rem_alias_lines)
|
||||
$ i = i + 1
|
||||
$ if line .eqs. "" then goto ex_rem_loop
|
||||
$ if line .eqs. "," then goto ex_rem_loop_end
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ line_out = line
|
||||
$ goto ex_rem_loop
|
||||
$ex_rem_loop_end:
|
||||
$ write pdsc line_out
|
||||
$ line_out = ""
|
||||
$ write pdsc " ) ;"
|
||||
$!
|
||||
$! execute upgrade
|
||||
$ write pdsc " execute upgrade ("
|
||||
$ i = 0
|
||||
$ex_upg_loop:
|
||||
$ line = f$element(i, ",", rem_alias_lines)
|
||||
$ i = i + 1
|
||||
$ if line .eqs. "" then goto ex_upg_loop
|
||||
$ if line .eqs. "," then goto ex_upg_loop_end
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ line_out = line
|
||||
$ goto ex_upg_loop
|
||||
$ex_upg_loop_end:
|
||||
$ write pdsc line_out
|
||||
$ line_out = ""
|
||||
$! remove aliases
|
||||
$ write pdsc " ) ;"
|
||||
$!
|
||||
$! execute postinstall
|
||||
$ write pdsc " execute postinstall ("
|
||||
$ if arch_code .nes. "V"
|
||||
$ then
|
||||
$ line_out = " ""set process/parse=extended"""
|
||||
$ endif
|
||||
$ i = 0
|
||||
$ex_pins_loop:
|
||||
$ line = f$element(i, ",", add_alias_lines)
|
||||
$ i = i + 1
|
||||
$ if line .eqs. "" then goto ex_pins_loop
|
||||
$ if line .eqs. "," then goto ex_pins_loop_end
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ line_out = line
|
||||
$ goto ex_pins_loop
|
||||
$ex_pins_loop_end:
|
||||
$ if line_out .eqs. "" then line_out = " ""continue"""
|
||||
$! write pdsc line_out
|
||||
$! line_out = ""
|
||||
$! add aliases and follow with renames.
|
||||
$!
|
||||
$goto inst_dir
|
||||
$!
|
||||
$inst_dir_loop:
|
||||
$ read/end=inst_alias_loop_end flst line_in
|
||||
$ line_in = f$edit(line_in,"compress,trim,uncomment")
|
||||
$ if line_in .eqs. "" then goto inst_dir_loop
|
||||
$inst_dir:
|
||||
$ pathname = f$element(0, " ", line_in)
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ if pathname .eqs. "[gnv]usr.dir"
|
||||
$ then
|
||||
$ pathname = "[gnv]beta.dir"
|
||||
$ else
|
||||
$ old_start = f$locate("[gnv.usr", pathname)
|
||||
$ if old_start .lt. f$length(pathname)
|
||||
$ then
|
||||
$ pathname = "[gnv.beta" + pathname - "[gnv.usr"
|
||||
$ endif
|
||||
$ endif
|
||||
$ endif
|
||||
$!
|
||||
$! Ignore the directory entries for now.
|
||||
$!-----------------------------------------
|
||||
$ filedir = f$parse(pathname,,,"DIRECTORY")
|
||||
$ if pathname .eqs. filedir then goto inst_dir_loop
|
||||
$!
|
||||
$! process .dir extensions for rename
|
||||
$! If this is not a directory then start processing files.
|
||||
$!-------------------------
|
||||
$ filetype = f$parse(pathname,,,"TYPE")
|
||||
$ filetype_u = f$edit(filetype, "upcase")
|
||||
$ filename = f$parse(pathname,,,"NAME")
|
||||
$ if filetype_u .nes. ".DIR" then goto inst_file
|
||||
$!
|
||||
$! process directory lines for rename.
|
||||
$!--------------------------------------
|
||||
$ if line_out .nes. ""
|
||||
$ then
|
||||
$ write pdsc line_out,","
|
||||
$ line_out = ""
|
||||
$ endif
|
||||
$ if arch_code .nes. "V"
|
||||
$ then
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ line_out = " ""rename pcsi$destination:''pathname' ''filename'.DIR"""
|
||||
$ else
|
||||
$ if line_out .nes. "" then write pdsc line_out
|
||||
$ line_out = ""
|
||||
$ endif
|
||||
$ goto inst_dir_loop
|
||||
$!
|
||||
$!
|
||||
$! process file lines for rename
|
||||
$!---------------------------------
|
||||
$inst_file_loop:
|
||||
$ read/end=inst_alias_loop_end flst line_in
|
||||
$ line_in = f$edit(line_in,"compress,trim,uncomment")
|
||||
$ if line_in .eqs. "" then goto inst_dir_loop
|
||||
$ pathname = f$element(0, " ", line_in)
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ if pathname .eqs. "[gnv]usr.dir"
|
||||
$ then
|
||||
$ pathname = "[gnv]beta.dir"
|
||||
$ else
|
||||
$ old_start = f$locate("[gnv.usr", pathname)
|
||||
$ if old_start .lt. f$length(pathname)
|
||||
$ then
|
||||
$ pathname = "[gnv.beta" + pathname - "[gnv.usr"
|
||||
$ endif
|
||||
$ endif
|
||||
$ endif
|
||||
$!
|
||||
$! Filenames with $ in them are VMS special and do not need to be lowercased.
|
||||
$! --------------------------------------------------------------------------
|
||||
$ if f$locate("$", pathname) .lt. f$length(pathname) then goto inst_file_loop
|
||||
$!
|
||||
$ filetype = f$parse(pathname,,,"TYPE")
|
||||
$ filename = f$parse(pathname,,,"NAME") + filetype
|
||||
$inst_file:
|
||||
$ if arch_code .nes. "V"
|
||||
$ then
|
||||
$ if line_out .nes. "" then write pdsc line_out,","
|
||||
$ filetype = f$parse(pathname,,,"TYPE")
|
||||
$ filename = f$parse(pathname,,,"NAME") + filetype
|
||||
$ line_out = " ""rename pcsi$destination:''pathname' ''filename'"""
|
||||
$ else
|
||||
$ if line_out .nes. "" then write pdsc line_out
|
||||
$ line_out = ""
|
||||
$ endif
|
||||
$ goto inst_file_loop
|
||||
$!
|
||||
$inst_alias_loop_end:
|
||||
$!
|
||||
$write pdsc line_out
|
||||
$write pdsc " ) ;"
|
||||
$close flst
|
||||
$!
|
||||
$! Move Release Notes to destination
|
||||
$!-------------------------------------
|
||||
$write pdsc " information RELEASE_NOTES phase after ;"
|
||||
$!
|
||||
$! Source kit option
|
||||
$!---------------------
|
||||
$write pdsc " option SOURCE default 0;"
|
||||
$write pdsc " directory ""[gnv.common_src]"" PROTECTION PUBLIC ;"
|
||||
$write pdsc -
|
||||
" file ""[gnv.common_src]''filename_base'_original_src.bck"""
|
||||
$write pdsc -
|
||||
" source [common_src]''filename_base'_original_src.bck ;"
|
||||
$if f$search("gnv$gnu:[vms_src]''filename_base'_vms_src.bck") .nes. ""
|
||||
$then
|
||||
$ write pdsc " directory ""[gnv.vms_src]"" PROTECTION PUBLIC ;"
|
||||
$ write pdsc " file ""[gnv.vms_src]''filename_base'_vms_src.bck"""
|
||||
$ write pdsc " source [vms_src]''filename_base'_vms_src.bck ;"
|
||||
$endif
|
||||
$write pdsc " end option;"
|
||||
$!
|
||||
$!
|
||||
$! Read through the file list again.
|
||||
$!----------------------------------
|
||||
$open/read flst pcsi_gnv_curl_file_list.txt
|
||||
$!
|
||||
$!
|
||||
$! Create directory lines
|
||||
$!-------------------------
|
||||
$flst_dir_loop:
|
||||
$ read/end=flst_loop_end flst line_in
|
||||
$ line_in = f$edit(line_in,"compress,trim,uncomment")
|
||||
$ if line_in .eqs. "" then goto flst_dir_loop
|
||||
$!
|
||||
$ filename = f$element(0, " ", line_in)
|
||||
$ linkflag = f$element(1, " ", line_in)
|
||||
$ if linkflag .eqs. "->" then goto flst_dir_loop
|
||||
$!
|
||||
$! Ignore .dir extensions
|
||||
$!-------------------------
|
||||
$ filetype = f$edit(f$parse(filename,,,"TYPE"), "upcase")
|
||||
$ if filetype .eqs. ".DIR" then goto flst_dir_loop
|
||||
$!
|
||||
$ destname = filename
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ old_start = f$locate("[gnv.usr", destname)
|
||||
$ if old_start .lt. f$length(destname)
|
||||
$ then
|
||||
$ destname = "[gnv.beta" + destname - "[gnv.usr"
|
||||
$ endif
|
||||
$ endif
|
||||
$!
|
||||
$! It should be just a directory then.
|
||||
$!-------------------------------------
|
||||
$ filedir = f$edit(f$parse(filename,,,"DIRECTORY"), "lowercase")
|
||||
$! If this is not a directory then start processing files.
|
||||
$!---------------------------------------------------------
|
||||
$ if filename .nes. filedir then goto flst_file
|
||||
$!
|
||||
$ write pdsc " directory ""''destname'"" PROTECTION PUBLIC ;"
|
||||
$ goto flst_dir_loop
|
||||
$!
|
||||
$!
|
||||
$! Add file lines for curl.
|
||||
$!---------------------------
|
||||
$flst_file_loop:
|
||||
$ read/end=flst_loop_end flst line_in
|
||||
$ line_in = f$edit(line_in,"compress,trim,uncomment")
|
||||
$ if line_in .eqs. "" then goto inst_file_loop
|
||||
$ filename = f$element(0, " ", line_in)
|
||||
$ destname = filename
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ old_start = f$locate("[gnv.usr", destname)
|
||||
$ if old_start .lt. f$length(destname)
|
||||
$ then
|
||||
$ destname = "[gnv.beta" + destname - "[gnv.usr"
|
||||
$ endif
|
||||
$ endif
|
||||
$flst_file:
|
||||
$ srcfile = filename - "gnv."
|
||||
$ write pdsc " file ""''destname'"" "
|
||||
$ write pdsc " source ""''srcfile'"" ;"
|
||||
$ goto flst_file_loop
|
||||
$!
|
||||
$flst_loop_end:
|
||||
$ close flst
|
||||
$!
|
||||
$! Add Link alias procedure file (N/A for curl)
|
||||
$!------------------------------------------------
|
||||
$!
|
||||
$! Add [.SYS$STARTUP]curl_startup file
|
||||
$!---------------------------------------
|
||||
$ if kit_type .eqs. "D"
|
||||
$ then
|
||||
$ write pdsc " file ""[sys$startup]curl_daily_startup.com"""
|
||||
$ else
|
||||
$ write pdsc " file ""[sys$startup]curl_startup.com"""
|
||||
$ endif
|
||||
$ write pdsc " source [usr.lib]curl_startup.com ;"
|
||||
$!
|
||||
$! Add Release notes file.
|
||||
$!------------------------------
|
||||
$ write pdsc -
|
||||
" file ""[SYSHLP]''filename_base'.release_notes"" release notes ;"
|
||||
$!
|
||||
$! Close the product file
|
||||
$!------------------------
|
||||
$ write pdsc "end product;"
|
||||
$!
|
||||
$close pdsc
|
||||
$!
|
||||
$all_exit:
|
||||
$ exit
|
198
packages/vms/build_gnv_curl_pcsi_text.com
Normal file
198
packages/vms/build_gnv_curl_pcsi_text.com
Normal file
@@ -0,0 +1,198 @@
|
||||
$! File: Build_GNV_curl_pcsi_text.com
|
||||
$!
|
||||
$! $Id$
|
||||
$!
|
||||
$! Build the *.pcsi$text file from the four components:
|
||||
$! 1. Generated =product header section
|
||||
$! 2. [--]readme. file from the Curl distribution, modified to fit
|
||||
$! a pcsi$text file format.
|
||||
$! 3. [--]copying file from the Curl distribution, modified to fit
|
||||
$! a pcsi$text file format.
|
||||
$! 4. Generated Producer section.
|
||||
$!
|
||||
$! Set the name of the release notes from the GNV_PCSI_FILENAME_BASE
|
||||
$!
|
||||
$! Copyright 2009, John Malmberg
|
||||
$!
|
||||
$! Permission to use, copy, modify, and/or distribute this software for any
|
||||
$! purpose with or without fee is hereby granted, provided that the above
|
||||
$! copyright notice and this permission notice appear in all copies.
|
||||
$!
|
||||
$! THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
$! WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
$! MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
$! ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
$! WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
$! ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
$! OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
$!
|
||||
$!
|
||||
$! 15-Jun-2009 J. Malmberg
|
||||
$!
|
||||
$!===========================================================================
|
||||
$!
|
||||
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
|
||||
$ if kit_name .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ producer = f$trnlnm("GNV_PCSI_PRODUCER")
|
||||
$ if producer .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ producer_full_name = f$trnlnm("GNV_PCSI_PRODUCER_FULL_NAME")
|
||||
$ if producer_full_name .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "@MAKE_PCSI_CURL_KIT_NAME.COM has not been run."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$!
|
||||
$! Parse the kit name into components.
|
||||
$!---------------------------------------
|
||||
$ producer = f$element(0, "-", kit_name)
|
||||
$ base = f$element(1, "-", kit_name)
|
||||
$ product = f$element(2, "-", kit_name)
|
||||
$ mmversion = f$element(3, "-", kit_name)
|
||||
$ majorver = f$extract(0, 3, mmversion)
|
||||
$ minorver = f$extract(3, 2, mmversion)
|
||||
$ updatepatch = f$element(4, "-", kit_name)
|
||||
$ if updatepatch .eqs. "-" then updatepatch = ""
|
||||
$!
|
||||
$!
|
||||
$ product_line = "=product ''producer' ''base' ''product'"
|
||||
$ if updatepatch .eqs. ""
|
||||
$ then
|
||||
$ product_name = " ''majorver'.''minorver'"
|
||||
$ else
|
||||
$ product_name = " ''majorver'.''minorver'-''updatepatch'"
|
||||
$ endif
|
||||
$ product_line = product_line + " ''product_name' full"
|
||||
$!
|
||||
$!
|
||||
$! If this is VAX and the file is on NFS, the names may be mangled.
|
||||
$!-----------------------------------------------------------------
|
||||
$ readme_file = ""
|
||||
$ if f$search("[--]readme.") .nes. ""
|
||||
$ then
|
||||
$ readme_file = "[--]readme."
|
||||
$ else
|
||||
$ if f$search("[--]$README.") .nes. ""
|
||||
$ then
|
||||
$ readme_file = "[--]$README."
|
||||
$ else
|
||||
$ write sys$output "Can not find readme file."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ endif
|
||||
$ copying_file = ""
|
||||
$ if f$search("[--]copying.") .nes. ""
|
||||
$ then
|
||||
$ copying_file = "[--]copying."
|
||||
$ else
|
||||
$ if f$search("[--]$COPYING.") .nes. ""
|
||||
$ then
|
||||
$ copying_file = "[--]$COPYING."
|
||||
$ else
|
||||
$ write sys$output "Can not find copying file."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$ endif
|
||||
$!
|
||||
$! Create the file as a VMS text file.
|
||||
$!----------------------------------------
|
||||
$ base_file = kit_name
|
||||
$ create 'base_file'.pcsi$text
|
||||
$!
|
||||
$!
|
||||
$! Start building file.
|
||||
$!----------------------
|
||||
$ open/append ptxt 'base_file'.pcsi$text
|
||||
$ write ptxt product_line
|
||||
$!
|
||||
$!
|
||||
$! First insert the Readme file.
|
||||
$!
|
||||
$ open/read rf 'readme_file'
|
||||
$!
|
||||
$ write ptxt "1 'PRODUCT"
|
||||
$ write ptxt "=prompt ''producter' ''product' for OpenVMS"
|
||||
$!
|
||||
$rf_loop:
|
||||
$ read/end=rf_loop_end rf line_in
|
||||
$ if line_in .nes. ""
|
||||
$ then
|
||||
$! PCSI files use the first character in for their purposes.
|
||||
$!--------------------------------------------------------------
|
||||
$ first_char = f$extract(0, 1, line_in)
|
||||
$ if first_char .nes. " " then line_in = " " + line_in
|
||||
$ endif
|
||||
$ write ptxt line_in
|
||||
$ goto rf_loop
|
||||
$rf_loop_end:
|
||||
$ close rf
|
||||
$!
|
||||
$!
|
||||
$! Now add in the copying file
|
||||
$!--------------------------------
|
||||
$ write ptxt ""
|
||||
$ write ptxt "1 'NOTICE"
|
||||
$ write ptxt ""
|
||||
$!
|
||||
$ open/read cf 'copying_file'
|
||||
$!
|
||||
$cf_loop:
|
||||
$ read/end=cf_loop_end cf line_in
|
||||
$ if line_in .nes. ""
|
||||
$ then
|
||||
$! PCSI files use the first character in for their purposes.
|
||||
$!--------------------------------------------------------------
|
||||
$ first_char = f$extract(0, 1, line_in)
|
||||
$ if first_char .nes. " " then line_in = " " + line_in
|
||||
$ endif
|
||||
$ write ptxt line_in
|
||||
$ goto cf_loop
|
||||
$cf_loop_end:
|
||||
$ close cf
|
||||
$!
|
||||
$! Now we need the rest of the boiler plate.
|
||||
$!--------------------------------------------
|
||||
$ write ptxt ""
|
||||
$ write ptxt "1 'PRODUCER"
|
||||
$ write ptxt "=prompt ''producer_full_name'"
|
||||
$ write ptxt -
|
||||
"This software product is provided by ''producer_full_name' with no warranty."
|
||||
$!
|
||||
$ arch_type = f$getsyi("ARCH_NAME")
|
||||
$ node_swvers = f$getsyi("node_swvers")
|
||||
$ vernum = f$extract(1, f$length(node_swvers), node_swvers)
|
||||
$ majver = f$element(0, ".", vernum)
|
||||
$ minverdash = f$element(1, ".", vernum)
|
||||
$ minver = f$element(0, "-", minverdash)
|
||||
$ dashver = f$element(1, "-", minverdash)
|
||||
$ if dashver .eqs. "-" then dashver = ""
|
||||
$ vmstag = majver + minver + dashver
|
||||
$ code = f$extract(0, 1, arch_type)
|
||||
$!
|
||||
$ write ptxt "1 NEED_VMS''vmstag'"
|
||||
$ write ptxt -
|
||||
"=prompt OpenVMS ''vernum' or later is not installed on your system."
|
||||
$ write ptxt "This product requires OpenVMS ''vernum' or later to function."
|
||||
$ write ptxt "1 NEED_ZLIB"
|
||||
$ write ptxt "=prompt ZLIB 1.2-8 or later is not installed on your system."
|
||||
$ write ptxt "This product requires ZLIB 1.2-8 or later to function."
|
||||
$ write ptxt "1 SOURCE"
|
||||
$ write ptxt "=prompt Source modules for ''product'"
|
||||
$ write ptxt "The Source modules for ''product' will be installed."
|
||||
$ write ptxt "1 RELEASE_NOTES"
|
||||
$ write ptxt "=prompt Release notes are available in the [SYSHLP] directory."
|
||||
$!
|
||||
$ close ptxt
|
||||
$!
|
||||
$!
|
||||
$!
|
||||
$all_exit:
|
||||
$ exit
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user