Compare commits
262 Commits
curl-7_32_
...
curl-7_33_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f77e89c5d2 | ||
![]() |
92cf6141ed | ||
![]() |
cf12d5b62f | ||
![]() |
39beaa5ffb | ||
![]() |
5df04bfafd | ||
![]() |
d015f4ccac | ||
![]() |
143d7c13d8 | ||
![]() |
9b33ecfd01 | ||
![]() |
ca1b34b887 | ||
![]() |
f0f95c97f7 | ||
![]() |
4cd444e01a | ||
![]() |
8264478490 | ||
![]() |
b46491900d | ||
![]() |
725288bf2f | ||
![]() |
173160c0d0 | ||
![]() |
3c3622b662 | ||
![]() |
a22c478ed7 | ||
![]() |
3d43a48781 | ||
![]() |
c8b05b809e | ||
![]() |
ca995010d0 | ||
![]() |
25a0c96a49 | ||
![]() |
a8b606b1a6 | ||
![]() |
20a99a45c0 | ||
![]() |
49341628b5 | ||
![]() |
ab7e6afd44 | ||
![]() |
4d7bf73fc3 | ||
![]() |
3c34f453fa | ||
![]() |
d5f687ed8f | ||
![]() |
a377fab015 | ||
![]() |
092f33d6bf | ||
![]() |
09a13a1c01 | ||
![]() |
30a09783b2 | ||
![]() |
733a4419d0 | ||
![]() |
77dc4ba877 | ||
![]() |
14d8209adc | ||
![]() |
a942d8ff5b | ||
![]() |
1695c67818 | ||
![]() |
f81d1e1666 | ||
![]() |
b71ed1fb3d | ||
![]() |
86ccfaa3fd | ||
![]() |
3b69462fc0 | ||
![]() |
22bccb0eda | ||
![]() |
4f591b9148 | ||
![]() |
52cefc8cd7 | ||
![]() |
8880f84e1a | ||
![]() |
9d4a8c7936 | ||
![]() |
fd8dc21fd0 | ||
![]() |
8ec6486d05 | ||
![]() |
59c1743c78 | ||
![]() |
60a2046162 | ||
![]() |
6dd8bd8d2f | ||
![]() |
b07709f741 | ||
![]() |
9215cee4c6 | ||
![]() |
34df869f99 | ||
![]() |
3f04d48495 | ||
![]() |
517b8e2290 | ||
![]() |
af44da38d6 | ||
![]() |
fcfa26a7ee | ||
![]() |
18db743851 | ||
![]() |
0e188e2dc3 | ||
![]() |
eecb0e969f | ||
![]() |
bd7d56ec71 | ||
![]() |
6f78aaad6f | ||
![]() |
89d320c2fd | ||
![]() |
b809bafb0c | ||
![]() |
3b6a1681dc | ||
![]() |
9300bb826d | ||
![]() |
dfe7ee1429 | ||
![]() |
841103c776 | ||
![]() |
8d2335ca23 | ||
![]() |
04064e89c1 | ||
![]() |
c873375123 | ||
![]() |
62d232c131 | ||
![]() |
98f7ca7e97 | ||
![]() |
4cfbb201c4 | ||
![]() |
dc016567ce | ||
![]() |
96b68c57ce | ||
![]() |
158dfe2c5c | ||
![]() |
8f5336a2fa | ||
![]() |
f8a9dbd391 | ||
![]() |
016879d477 | ||
![]() |
c03335ec68 | ||
![]() |
894585784c | ||
![]() |
33c1f2876b | ||
![]() |
00ee5c5cf1 | ||
![]() |
dadc495540 | ||
![]() |
eae86ba62d | ||
![]() |
e9cca79dd1 | ||
![]() |
4ba3b6c05a | ||
![]() |
187ac69374 | ||
![]() |
84ad1569e5 | ||
![]() |
45e0a661ce | ||
![]() |
4d6ef6297a | ||
![]() |
b68c52704b | ||
![]() |
4f4dc5832d | ||
![]() |
fbcefc0ce0 | ||
![]() |
83f6f58834 | ||
![]() |
0a691f8935 | ||
![]() |
c243d45aad | ||
![]() |
8a6dba520b | ||
![]() |
32352ed6ad | ||
![]() |
df69440d05 | ||
![]() |
345955e87e | ||
![]() |
6f5b46855c | ||
![]() |
5f93c5d658 | ||
![]() |
7fd84b14d2 | ||
![]() |
f2403140f9 | ||
![]() |
f3c9749a40 | ||
![]() |
3f6991766f | ||
![]() |
cfe5f7dbf4 | ||
![]() |
5840c918d5 | ||
![]() |
b0afb00000 | ||
![]() |
0b5ae7c80e | ||
![]() |
0d55f4e1bc | ||
![]() |
86d340af27 | ||
![]() |
5c14a7f068 | ||
![]() |
2879ffacfa | ||
![]() |
d89eb55906 | ||
![]() |
4a85e60cfe | ||
![]() |
bfefe2400a | ||
![]() |
25c6890375 | ||
![]() |
eb6314260d | ||
![]() |
313c38c9de | ||
![]() |
ae6096471a | ||
![]() |
66ea5c415b | ||
![]() |
2481ac358c | ||
![]() |
c639d725a3 | ||
![]() |
857f999353 | ||
![]() |
6d9cddc513 | ||
![]() |
e20e48cbf2 | ||
![]() |
ee5e2cf6cb | ||
![]() |
e8313697b6 | ||
![]() |
28427b4083 | ||
![]() |
131649a121 | ||
![]() |
632b3d81d6 | ||
![]() |
241aeadc50 | ||
![]() |
669e4ca366 | ||
![]() |
c9617d9f93 | ||
![]() |
f8986a2b34 | ||
![]() |
1b96ce04b2 | ||
![]() |
f851df88fb | ||
![]() |
18c595fde2 | ||
![]() |
56abdd07e7 | ||
![]() |
7e06c336d6 | ||
![]() |
8a4069fb17 | ||
![]() |
243ad539fe | ||
![]() |
3d60590422 | ||
![]() |
08fa4fed70 | ||
![]() |
4344fa926a | ||
![]() |
61672bde44 | ||
![]() |
13dbb41c49 | ||
![]() |
e5c2354fd5 | ||
![]() |
09634f46fb | ||
![]() |
0119a93b33 | ||
![]() |
9fa42beddc | ||
![]() |
d6cda9e8ab | ||
![]() |
2a7f1425d9 | ||
![]() |
900ccc26ae | ||
![]() |
01d7bbbebe | ||
![]() |
3dc6fc42bf | ||
![]() |
d2fe616e7e | ||
![]() |
316ca865e3 | ||
![]() |
812d49db90 | ||
![]() |
02370fff3a | ||
![]() |
e9de8e78f0 | ||
![]() |
2eabb7d590 | ||
![]() |
d707a975f6 | ||
![]() |
ac487842a1 | ||
![]() |
06b6e1d0d2 | ||
![]() |
b77997e6da | ||
![]() |
9e8ced9890 | ||
![]() |
698e3bdf82 | ||
![]() |
9011fb3f0c | ||
![]() |
073b03fab7 | ||
![]() |
f73f052010 | ||
![]() |
97ed1ac905 | ||
![]() |
322f0bc2f1 | ||
![]() |
af4bddf20b | ||
![]() |
f19efd07e7 | ||
![]() |
83f5332536 | ||
![]() |
497775024c | ||
![]() |
ea38a70539 | ||
![]() |
5eea336d01 | ||
![]() |
f3849a7b84 | ||
![]() |
1ca6ed7b75 | ||
![]() |
aa51d3a139 | ||
![]() |
64c8909071 | ||
![]() |
e848942505 | ||
![]() |
7e489c42f7 | ||
![]() |
75b52f9dcc | ||
![]() |
221825aebf | ||
![]() |
9d35ad9552 | ||
![]() |
c4a7ca038e | ||
![]() |
84f3b3dd44 | ||
![]() |
2ef83136d4 | ||
![]() |
d737aa19c8 | ||
![]() |
78e6683bb0 | ||
![]() |
2f9b64ac33 | ||
![]() |
6a353049ac | ||
![]() |
49e3d803ab | ||
![]() |
b644ae68c8 | ||
![]() |
4ae7b7ea69 | ||
![]() |
13a2e32548 | ||
![]() |
c3b513e75c | ||
![]() |
a74b36af2a | ||
![]() |
1b4dc10393 | ||
![]() |
45b6e2dd89 | ||
![]() |
6dca35c0e5 | ||
![]() |
a691e04470 | ||
![]() |
3d1a453d88 | ||
![]() |
d7a39f8f97 | ||
![]() |
3c929ff9f6 | ||
![]() |
9d957294cb | ||
![]() |
acf59be7f0 | ||
![]() |
e7dcc454c6 | ||
![]() |
84789e12fb | ||
![]() |
460fb12097 | ||
![]() |
63d8b3a507 | ||
![]() |
90ab65c632 | ||
![]() |
34122800b8 | ||
![]() |
7f41eab395 | ||
![]() |
0192ad65bb | ||
![]() |
06c1bea72f | ||
![]() |
19a05c908f | ||
![]() |
bb55293313 | ||
![]() |
817ceb09e0 | ||
![]() |
1a911f7ec4 | ||
![]() |
ea464d72e9 | ||
![]() |
22adb46a32 | ||
![]() |
fc99eaa5ae | ||
![]() |
4bea91fc67 | ||
![]() |
06d1b10cbe | ||
![]() |
816b639035 | ||
![]() |
8804ffd4fa | ||
![]() |
19122c0768 | ||
![]() |
c346c4c8f9 | ||
![]() |
bc7d806e3a | ||
![]() |
6cf8413e31 | ||
![]() |
062e5bfd9c | ||
![]() |
e4a1888bd0 | ||
![]() |
2f1a0bc0bf | ||
![]() |
09ddb1d61c | ||
![]() |
15f76bf7bb | ||
![]() |
36585b5395 | ||
![]() |
11baffbff6 | ||
![]() |
53333a43a1 | ||
![]() |
c56f9797e7 | ||
![]() |
9281be36d5 | ||
![]() |
f15a88f2b2 | ||
![]() |
5ca96cb844 | ||
![]() |
10afe7cf10 | ||
![]() |
6972335f50 | ||
![]() |
d5e2d0b6bf | ||
![]() |
f34b5fb4d8 | ||
![]() |
f584312e81 | ||
![]() |
0b4557f766 | ||
![]() |
204126a5f1 | ||
![]() |
2ae3d28f3d | ||
![]() |
8a42c2ef8d | ||
![]() |
e79535bc5e | ||
![]() |
4ad8e142da | ||
![]() |
e3ee73b70c |
172
RELEASE-NOTES
172
RELEASE-NOTES
@@ -1,69 +1,68 @@
|
||||
Curl and libcurl 7.32.0
|
||||
Curl and libcurl 7.33.0
|
||||
|
||||
Public curl releases: 134
|
||||
Command line options: 152
|
||||
curl_easy_setopt() options: 199
|
||||
Public curl releases: 135
|
||||
Command line options: 161
|
||||
curl_easy_setopt() options: 205
|
||||
Public functions in libcurl: 58
|
||||
Known libcurl bindings: 42
|
||||
Contributors: 1049
|
||||
|
||||
***
|
||||
krb4 support is up for removal. If you care about it at all, speak up
|
||||
on the curl-library list asap!
|
||||
***
|
||||
Contributors: 1057
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
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
|
||||
o test code for testing the event based API [3]
|
||||
o CURLM_ADDED_ALREADY: new error code
|
||||
o test TFTP server: support "writedelay" within <servercmd>
|
||||
o krb4 support has been removed
|
||||
o imap/pop3/smtp: added basic SASL XOAUTH2 support [9]
|
||||
o darwinssl: add support for PKCS#12 files for client authentication
|
||||
o darwinssl: enable BEAST workaround on iOS 7 & later
|
||||
o Pass password to OpenSSL engine by user interface [15]
|
||||
o c-ares: Add support for various DNS binding options
|
||||
o cookies: add expiration
|
||||
o curl: added --oauth2-bearer option
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
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
|
||||
o nss: make sure that NSS is initialized
|
||||
o curl: make --no-[option] work properly for several options
|
||||
o FTP: with socket_action send better socket updates in active mode [1]
|
||||
o curl: fix the --sasl-ir in the --help output
|
||||
o tests 2032, 2033: Don't hardcode port in expected output
|
||||
o urlglob: better detect unclosed braces, empty lists and overflows [7]
|
||||
o urlglob: error out on range overflow [8]
|
||||
o imap: Fixed response check for SEARCH, EXPUNGE, LSUB, UID and NOOP commands [10]
|
||||
o handle arbitrary-length username and password [2]
|
||||
o TFTP: make the CURLOPT_LOW_SPEED* options work [4]
|
||||
o curl.h: name space pollution by "enum type" [5]
|
||||
o multi: move on from STATE_DONE faster [6]
|
||||
o FTP: 60 secs delay if aborted in the CURLOPT_HEADERFUNCTION callback [11]
|
||||
o multi_socket: improved 100-continue timeout handling
|
||||
o curl_multi_remove_handle: allow multiple removes
|
||||
o FTP: fix getsock during DO_MORE state [12]
|
||||
o -x: rephrased the --proxy section somewhat
|
||||
o acinclude: fix --without-ca-path when cross-compiling [13]
|
||||
o LDAP: fix bad free() when URL parsing failed [14]
|
||||
o --data: mention CRLF treatment when reading from file
|
||||
o curl_easy_pause: suggest one way to unpause
|
||||
o imap: Fixed calculation of transfer when partial FETCH received [16]
|
||||
o pingpong: Check SSL library buffers for already read data [16]
|
||||
o imap/pop3/smtp: Speed up SSL connection initialization
|
||||
o libcurl.3: for multi interface connections are held in the multi handle
|
||||
o curl_easy_setopt.3: mention RTMP URL quirks [17]
|
||||
o curl.1: detail how short/long options work [18]
|
||||
o curl.1: Added information about optional login options to --user option
|
||||
o curl: Added clarification to the --mail options in the --help output
|
||||
o curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value
|
||||
o openssl: use correct port number in error message [19]
|
||||
o darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher
|
||||
o OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER
|
||||
o xattr: add support for FreeBSD xattr API
|
||||
o win32: fix Visual Studio 2010 build with WINVER >= 0x600 [22]
|
||||
o configure: use icc options without space [21]
|
||||
o test1112: Increase the timeout from 7s to 16s [20]
|
||||
o SCP: upload speed on a fast connection limited to 16384 B/s
|
||||
o curl_setup_once: fix errno access for lwip on Windows [24]
|
||||
o HTTP: Output http response 304 when modified time is too old [23]
|
||||
|
||||
This release includes the following known bugs:
|
||||
|
||||
@@ -72,34 +71,41 @@ 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:
|
||||
|
||||
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,
|
||||
|
||||
Alex McLellan, Bill Doyle, Colby Ranger, Fabian Keil, Gisle Vanem,
|
||||
John E. Malmberg, Jonathan Nieder, Kamil Dudka, Shawn Landden,
|
||||
Tor Arntsen, Will Dietz, Yi Huang, Kyle L. Huff, Steve Holme, Mike Mio,
|
||||
Stefan Neis, Nick Zitzmann, Geoff Beier, John Dunn, Jiri Hruska,
|
||||
Tomas Mlcoch, Kim Vandry, Ben Greear, Gorilla Maguila, Jerry Krinock,
|
||||
Yamada Yasuharu, Gordon Marler, Dave Thompson, D. Flinkmann,
|
||||
Benoit Sigoure, Clemens Gruber, Guenter Knauf, Petr Pisar, Elmira A Semenova,
|
||||
Francois Charlier, Ishan SinghLevett, Marcel Raad, Ulf Samuelsson,
|
||||
Andrej E Baranov, Derek Higgins, Heinrich Schaefer
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
[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
|
||||
[1] = http://curl.haxx.se/mail/lib-2013-08/0043.html
|
||||
[2] = http://bugs.debian.org/719856
|
||||
[3] = http://daniel.haxx.se/blog/2013/08/20/testing-curl_multi_socket_action/
|
||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1269
|
||||
[5] = https://github.com/bagder/curl/pull/76
|
||||
[6] = http://curl.haxx.se/mail/lib-2013-08/0211.html
|
||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1264
|
||||
[8] = http://curl.haxx.se/bug/view.cgi?id=1267
|
||||
[9] = http://curl.haxx.se/mail/lib-2013-08/0234.html
|
||||
[10] = http://curl.haxx.se/mail/lib-2013-08/0136.html
|
||||
[11] = https://bugzilla.redhat.com/1005686
|
||||
[12] = http://curl.haxx.se/mail/lib-2013-08/0109.html
|
||||
[13] = http://curl.haxx.se/bug/view.cgi?id=1273
|
||||
[14] = http://curl.haxx.se/mail/lib-2013-08/0209.html
|
||||
[15] = http://curl.haxx.se/mail/lib-2013-08/0265.html
|
||||
[16] = http://curl.haxx.se/mail/lib-2013-08/0170.html
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1278
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1279
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1281
|
||||
[20] = http://curl.haxx.se/mail/lib-2010-02/0200.html
|
||||
[21] = http://curl.haxx.se/mail/lib-2013-09/0182.html
|
||||
[22] = http://curl.haxx.se/bug/view.cgi?id=1282
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1288
|
||||
[24] = http://curl.haxx.se/mail/lib-2013-10/0048.html
|
||||
|
13
acinclude.m4
13
acinclude.m4
@@ -2619,18 +2619,18 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
fi
|
||||
capath="$want_capath"
|
||||
ca="no"
|
||||
elif test "x$cross_compiling" != "xyes"; then
|
||||
dnl NOT cross-compiling and...
|
||||
dnl neither of the --with-ca-* options are provided
|
||||
|
||||
else
|
||||
dnl first try autodetecting a CA bundle , then a CA path
|
||||
dnl both autodetections can be skipped by --without-ca-*
|
||||
ca="no"
|
||||
capath="no"
|
||||
if test "x$cross_compiling" != "xyes"; then
|
||||
dnl NOT cross-compiling and...
|
||||
dnl neither of the --with-ca-* options are provided
|
||||
if test "x$want_ca" = "xunset"; then
|
||||
dnl the path we previously would have installed the curl ca bundle
|
||||
dnl to, and thus we now check for an already existing cert in that place
|
||||
dnl in case we find no other
|
||||
dnl to, and thus we now check for an already existing cert in that
|
||||
dnl place in case we find no other
|
||||
if test "x$prefix" != xNONE; then
|
||||
cac="${prefix}/share/curl/curl-ca-bundle.crt"
|
||||
else
|
||||
@@ -2662,6 +2662,7 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
dnl no option given and cross-compiling
|
||||
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$ca" != "xno"; then
|
||||
CURL_CA_BUNDLE='"'$ca'"'
|
||||
|
191
configure.ac
191
configure.ac
@@ -150,7 +150,6 @@ dnl initialize all the info variables
|
||||
curl_ssl_msg="no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )"
|
||||
curl_ssh_msg="no (--with-libssh2)"
|
||||
curl_zlib_msg="no (--with-zlib)"
|
||||
curl_krb4_msg="no (--with-krb4*)"
|
||||
curl_gss_msg="no (--with-gssapi)"
|
||||
curl_spnego_msg="no (--with-spnego)"
|
||||
curl_tls_srp_msg="no (--enable-tls-srp)"
|
||||
@@ -1134,101 +1133,6 @@ no)
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for the presence of Kerberos4 libraries and headers
|
||||
dnl **********************************************************************
|
||||
|
||||
AC_ARG_WITH(krb4-includes,
|
||||
AC_HELP_STRING([--with-krb4-includes=DIR],
|
||||
[Specify location of kerberos4 headers]),[
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"
|
||||
KRB4INC="$withval"
|
||||
want_krb4=yes
|
||||
])
|
||||
|
||||
AC_ARG_WITH(krb4-libs,
|
||||
AC_HELP_STRING([--with-krb4-libs=DIR],[Specify location of kerberos4 libs]),[
|
||||
LDFLAGS="$LDFLAGS -L$withval"
|
||||
KRB4LIB="$withval"
|
||||
want_krb4=yes
|
||||
])
|
||||
|
||||
|
||||
OPT_KRB4=off
|
||||
AC_ARG_WITH(krb4,dnl
|
||||
AC_HELP_STRING([--with-krb4=DIR],[where to look for Kerberos4]),[
|
||||
OPT_KRB4="$withval"
|
||||
if test X"$OPT_KRB4" != Xno; then
|
||||
want_krb4="yes"
|
||||
if test X"$OPT_KRB4" != Xyes; then
|
||||
LDFLAGS="$LDFLAGS -L$OPT_KRB4/lib$libsuff"
|
||||
KRB4LIB="$OPT_KRB4/lib$libsuff"
|
||||
CPPFLAGS="$CPPFLAGS -I$OPT_KRB4/include"
|
||||
KRB4INC="$OPT_KRB4/include"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([if Kerberos4 support is requested])
|
||||
|
||||
if test "$want_krb4" = yes
|
||||
then
|
||||
if test "$ipv6" = "yes"; then
|
||||
echo krb4 is not compatible with IPv6
|
||||
exit 1
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
dnl Check for & handle argument to --with-krb4
|
||||
|
||||
AC_MSG_CHECKING(where to look for Kerberos4)
|
||||
if test X"$OPT_KRB4" = Xyes
|
||||
then
|
||||
AC_MSG_RESULT([defaults])
|
||||
else
|
||||
AC_MSG_RESULT([libs in $KRB4LIB, headers in $KRB4INC])
|
||||
fi
|
||||
|
||||
dnl Check for DES library
|
||||
AC_CHECK_LIB(des, des_pcbc_encrypt,
|
||||
[
|
||||
AC_CHECK_HEADERS(des.h)
|
||||
|
||||
dnl resolv lib?
|
||||
AC_CHECK_FUNC(res_search, , [AC_CHECK_LIB(resolv, res_search)])
|
||||
|
||||
dnl Check for the Kerberos4 library
|
||||
AC_CHECK_LIB(krb, krb_net_read,
|
||||
[
|
||||
dnl Check for header files
|
||||
AC_CHECK_HEADERS(krb.h)
|
||||
|
||||
dnl we found the required libraries, add to LIBS
|
||||
LIBS="-lkrb -lcom_err -ldes $LIBS"
|
||||
|
||||
dnl Check for function krb_get_our_ip_for_realm
|
||||
dnl this is needed for NAT networks
|
||||
AC_CHECK_FUNCS(krb_get_our_ip_for_realm)
|
||||
|
||||
dnl add define KRB4
|
||||
AC_DEFINE(HAVE_KRB4, 1,
|
||||
[if you have the Kerberos4 libraries (including -ldes)])
|
||||
|
||||
dnl substitute it too!
|
||||
KRB4_ENABLED=1
|
||||
AC_SUBST(KRB4_ENABLED)
|
||||
|
||||
curl_krb4_msg="enabled"
|
||||
|
||||
dnl the krb4 stuff needs a strlcpy()
|
||||
AC_CHECK_FUNCS(strlcpy)
|
||||
|
||||
])
|
||||
])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for FBopenssl(SPNEGO) libraries
|
||||
dnl **********************************************************************
|
||||
@@ -2808,6 +2712,92 @@ dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \
|
||||
dnl genprogc/thread_quick_ref.htm
|
||||
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for nghttp2
|
||||
dnl **********************************************************************
|
||||
|
||||
AC_MSG_CHECKING([whether to build with nghttp2])
|
||||
OPT_H2="no"
|
||||
AC_ARG_WITH(nghttp2,
|
||||
AC_HELP_STRING([--with-nghttp2=PATH],[Enable nghttp2 usage])
|
||||
AC_HELP_STRING([--without-nghttp2],[Disable nghttp2 usage]),
|
||||
[OPT_H2=$withval])
|
||||
case "$OPT_H2" in
|
||||
no)
|
||||
dnl --without-nghttp2 option used
|
||||
want_idn="no"
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
default)
|
||||
dnl configure option not specified
|
||||
want_h2="no"
|
||||
want_h2_path="default"
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
yes)
|
||||
dnl --with-nghttp2 option used without path
|
||||
want_h2="yes"
|
||||
want_h2_path=""
|
||||
AC_MSG_RESULT([yes])
|
||||
;;
|
||||
*)
|
||||
dnl --with-nghttp2 option used with path
|
||||
want_h2="yes"
|
||||
want_h2_path="$withval"
|
||||
AC_MSG_RESULT([yes ($withval)])
|
||||
;;
|
||||
esac
|
||||
|
||||
curl_h2_msg="disabled (--with-nghttp2)"
|
||||
if test X"$OPT_H2" != Xno; then
|
||||
dnl backup the pre-librtmp variables
|
||||
CLEANLDFLAGS="$LDFLAGS"
|
||||
CLEANCPPFLAGS="$CPPFLAGS"
|
||||
CLEANLIBS="$LIBS"
|
||||
|
||||
h2pcdir=${want_h2_path}/lib/pkgconfig
|
||||
CURL_CHECK_PKGCONFIG(libnghttp2, $h2pcdir)
|
||||
|
||||
if test "$PKGCONFIG" != "no" ; then
|
||||
LIB_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
|
||||
$PKGCONFIG --libs-only-l libnghttp2`
|
||||
AC_MSG_NOTICE([-l is $LIB_H2])
|
||||
|
||||
CPP_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) dnl
|
||||
$PKGCONFIG --cflags-only-I libnghttp2`
|
||||
AC_MSG_NOTICE([-I is $CPP_H2])
|
||||
|
||||
LD_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
|
||||
$PKGCONFIG --libs-only-L libnghttp2`
|
||||
AC_MSG_NOTICE([-L is $LD_H2])
|
||||
|
||||
else
|
||||
dnl To avoid link errors, we do not allow --libnghttp2 without
|
||||
dnl a pkgconfig file
|
||||
AC_MSG_ERROR([--with-nghttp2 was specified but could not find libnghttp2 pkg-config file.])
|
||||
fi
|
||||
|
||||
LDFLAGS="$LDFLAGS $LD_H2"
|
||||
CPPFLAGS="$CPPFLAGS $CPP_H2"
|
||||
LIBS="$LIB_H2 $LIBS"
|
||||
|
||||
AC_CHECK_LIB(nghttp2, nghttp2_session_client_new,
|
||||
[
|
||||
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
|
||||
curl_h2_msg="enabled (nghttp2)"
|
||||
NGHTTP2_ENABLED=1
|
||||
AC_DEFINE(USE_NGHTTP2, 1, [if nghttp2 is in use])
|
||||
AC_SUBST(USE_NGHTTP2, [1])
|
||||
)
|
||||
],
|
||||
dnl not found, revert back to clean variables
|
||||
LDFLAGS=$CLEANLDFLAGS
|
||||
CPPFLAGS=$CLEANCPPFLAGS
|
||||
LIBS=$CLEANLIBS
|
||||
)
|
||||
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Back to "normal" configuring
|
||||
dnl **********************************************************************
|
||||
@@ -3365,9 +3355,6 @@ if test "x$USE_SSLEAY" = "x1"; then
|
||||
elif test -n "$SSL_ENABLED"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SSL"
|
||||
fi
|
||||
if test "@KRB4_ENABLED@" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4"
|
||||
fi
|
||||
if test "x$IPV6_ENABLED" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
|
||||
fi
|
||||
@@ -3397,6 +3384,10 @@ if test "x$USE_TLS_SRP" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
|
||||
fi
|
||||
|
||||
if test "x$USE_NGHTTP2" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
|
||||
fi
|
||||
|
||||
AC_SUBST(SUPPORT_FEATURES)
|
||||
|
||||
dnl For supported protocols in pkg-config file
|
||||
@@ -3542,7 +3533,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
SSL support: ${curl_ssl_msg}
|
||||
SSH support: ${curl_ssh_msg}
|
||||
zlib support: ${curl_zlib_msg}
|
||||
krb4 support: ${curl_krb4_msg}
|
||||
GSSAPI support: ${curl_gss_msg}
|
||||
SPNEGO support: ${curl_spnego_msg}
|
||||
TLS-SRP support: ${curl_tls_srp_msg}
|
||||
@@ -3561,6 +3551,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
RTSP support: ${curl_rtsp_msg}
|
||||
RTMP support: ${curl_rtmp_msg}
|
||||
metalink support: ${curl_mtlnk_msg}
|
||||
HTTP2 support: ${curl_h2_msg}
|
||||
Protocols: ${SUPPORT_PROTOCOLS}
|
||||
])
|
||||
|
||||
|
46
contributors.sh
Executable file
46
contributors.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
#
|
||||
# This script shows all mentioned contributors from <hash> until HEAD. To aid
|
||||
# when writing RELEASE-NOTES and THANKS.
|
||||
#
|
||||
|
||||
start=$1
|
||||
|
||||
if test -z "$start"; then
|
||||
echo "Usage: $0 <since this tag/hash>"
|
||||
fi
|
||||
|
||||
# filter out Author:, Commit: and *by: lines
|
||||
# cut off the email parts
|
||||
# cut off spaces first and last on the line
|
||||
# only count names with a space (ie more than one word)
|
||||
# sort all unique names
|
||||
git log $start..HEAD | \
|
||||
egrep '(Author|Commit|by):' | \
|
||||
cut -d: -f2- | \
|
||||
cut '-d<' -f1 | \
|
||||
sed -e 's/^ //' -e 's/ $//g' | \
|
||||
grep ' ' | \
|
||||
sort -u
|
102
docs/FAQ
102
docs/FAQ
@@ -202,27 +202,25 @@ FAQ
|
||||
better. We do however believe in a few rules when it comes to the future of
|
||||
curl:
|
||||
|
||||
* Curl -- the command line tool -- is to remain a non-graphical command line
|
||||
tool. If you want GUIs or fancy scripting capabilities, you should look
|
||||
for another tool that uses libcurl.
|
||||
Curl -- the command line tool -- is to remain a non-graphical command line
|
||||
tool. If you want GUIs or fancy scripting capabilities, you should look for
|
||||
another tool that uses libcurl.
|
||||
|
||||
* We do not add things to curl that other small and available tools already
|
||||
do very fine at the side. Curl's output is fine to pipe into another
|
||||
program or redirect to another file for the next program to interpret.
|
||||
We do not add things to curl that other small and available tools already do
|
||||
very fine at the side. Curl's output is fine to pipe into another program or
|
||||
redirect to another file for the next program to interpret.
|
||||
|
||||
* We focus on protocol related issues and improvements. If you wanna do more
|
||||
magic with the supported protocols than curl currently does, chances are
|
||||
big we will agree. If you wanna add more protocols, we may very well
|
||||
agree.
|
||||
We focus on protocol related issues and improvements. If you wanna do more
|
||||
magic with the supported protocols than curl currently does, chances are big
|
||||
we will agree. If you wanna add more protocols, we may very well agree.
|
||||
|
||||
* If you want someone else to make all the work while you wait for us to
|
||||
If you want someone else to make all the work while you wait for us to
|
||||
implement it for you, that is not a very friendly attitude. We spend a
|
||||
considerable time already on maintaining and developing curl. In order to
|
||||
get more out of us, you should consider trading in some of your time and
|
||||
efforts in return.
|
||||
|
||||
* If you write the code, chances are bigger that it will get into curl
|
||||
faster.
|
||||
If you write the code, chances are bigger that it will get into curl faster.
|
||||
|
||||
1.5 Who makes curl?
|
||||
|
||||
@@ -263,7 +261,7 @@ FAQ
|
||||
|
||||
Our project name curl has been in effective use since 1998. We were not the
|
||||
first computer related project to use the name "curl" and do not claim any
|
||||
first-hand rights to the name.
|
||||
rights to the name.
|
||||
|
||||
We recognize that we will be living in parallel with curl.com and wish them
|
||||
every success.
|
||||
@@ -620,15 +618,15 @@ FAQ
|
||||
|
||||
Some workarounds usually suggested to overcome this Javascript dependency:
|
||||
|
||||
- Depending on the Javascript complexity, write up a script that
|
||||
translates it to another language and execute that.
|
||||
Depending on the Javascript complexity, write up a script that translates it
|
||||
to another language and execute that.
|
||||
|
||||
- Read the Javascript code and rewrite the same logic in another language.
|
||||
Read the Javascript code and rewrite the same logic in another language.
|
||||
|
||||
- Implement a Javascript interpreter, people have successfully used the
|
||||
Implement a Javascript interpreter, people have successfully used the
|
||||
Mozilla Javascript engine in the past.
|
||||
|
||||
- Ask your admins to stop this, for a static proxy setup or similar.
|
||||
Ask your admins to stop this, for a static proxy setup or similar.
|
||||
|
||||
3.15 Can I do recursive fetches with curl?
|
||||
|
||||
@@ -644,23 +642,27 @@ FAQ
|
||||
There are three different kinds of "certificates" to keep track of when we
|
||||
talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl.
|
||||
|
||||
- Client certificate. The server you communicate may require that you can
|
||||
provide this in order to prove that you actually are who you claim to be.
|
||||
If the server doesn't require this, you don't need a client certificate.
|
||||
CLIENT CERTIFICATE
|
||||
|
||||
The server you communicate may require that you can provide this in order to
|
||||
prove that you actually are who you claim to be. If the server doesn't
|
||||
require this, you don't need a client certificate.
|
||||
|
||||
A client certificate is always used together with a private key, and the
|
||||
private key has a pass phrase that protects it.
|
||||
|
||||
- Server certificate. The server you communicate with has a server
|
||||
certificate. You can and should verify this certificate to make sure that
|
||||
you are truly talking to the real server and not a server impersonating
|
||||
it.
|
||||
SERVER CERTIFICATE
|
||||
|
||||
- Certificate Authority certificate ("CA cert"). You often have several CA
|
||||
certs in a CA cert bundle that can be used to verify a server certificate
|
||||
that was signed by one of the authorities in the bundle. curl does not
|
||||
come with a CA cert bundle but most curl installs provide one. You can
|
||||
also override the default.
|
||||
The server you communicate with has a server certificate. You can and should
|
||||
verify this certificate to make sure that you are truly talking to the real
|
||||
server and not a server impersonating it.
|
||||
|
||||
CERTIFICATE AUTHORITY CERTIFICATE ("CA cert")
|
||||
|
||||
You often have several CA certs in a CA cert bundle that can be used to
|
||||
verify a server certificate that was signed by one of the authorities in the
|
||||
bundle. curl does not come with a CA cert bundle but most curl installs
|
||||
provide one. You can also override the default.
|
||||
|
||||
The server certificate verification process is made by using a Certificate
|
||||
Authority certificate ("CA cert") that was used to sign the server
|
||||
@@ -669,9 +671,9 @@ FAQ
|
||||
4.12 and the SSLCERTS document
|
||||
(http://curl.haxx.se/docs/sslcerts.html). Server certificates that are
|
||||
"self-signed" or otherwise signed by a CA that you do not have a CA cert
|
||||
for, cannot be verified. If the verification during a connect fails, you
|
||||
are refused access. You then need to explicitly disable the verification
|
||||
to connect to the server.
|
||||
for, cannot be verified. If the verification during a connect fails, you are
|
||||
refused access. You then need to explicitly disable the verification to
|
||||
connect to the server.
|
||||
|
||||
3.17 How do I list the root dir of an FTP server?
|
||||
|
||||
@@ -794,12 +796,13 @@ FAQ
|
||||
|
||||
curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
|
||||
|
||||
In Windows, the standard DOS shell treats the %-symbol specially and you
|
||||
need to use TWO %-symbols for each single one you want to use in the URL.
|
||||
In Windows, the standard DOS shell treats the percent sign specially and you
|
||||
need to use TWO percent signs for each single one you want to use in the
|
||||
URL.
|
||||
|
||||
Also note that if you want the literal %-symbol to be part of the data you
|
||||
pass in a POST using -d/--data you must encode it as '%25' (which then also
|
||||
needs the %-symbol doubled on Windows machines).
|
||||
If you want a literal percent sign to be part of the data you pass in a POST
|
||||
using -d/--data you must encode it as '%25' (which then also needs the
|
||||
percent sign doubled on Windows machines).
|
||||
|
||||
4.3 How can I use {, }, [ or ] to specify multiple URLs?
|
||||
|
||||
@@ -968,13 +971,13 @@ FAQ
|
||||
4.14 Redirects work in browser but not with curl!
|
||||
|
||||
curl supports HTTP redirects fine (see item 3.8). Browsers generally support
|
||||
at least two other ways to perform directs that curl does not:
|
||||
at least two other ways to perform redirects that curl does not:
|
||||
|
||||
- Meta tags. You can write a HTML tag that will cause the browser to
|
||||
redirect to another given URL after a certain time.
|
||||
Meta tags. You can write a HTML tag that will cause the browser to redirect
|
||||
to another given URL after a certain time.
|
||||
|
||||
- Javascript. You can write a Javascript program embedded in a HTML page
|
||||
that redirects the browser to another given URL.
|
||||
Javascript. You can write a Javascript program embedded in a HTML page that
|
||||
redirects the browser to another given URL.
|
||||
|
||||
There is no way to make curl follow these redirects. You must either
|
||||
manually figure out what the page is set to do, or you write a script that
|
||||
@@ -1270,17 +1273,18 @@ FAQ
|
||||
|
||||
5.12 Can I make libcurl fake or hide my real IP address?
|
||||
|
||||
No. libcurl operates on a higher level than so. Besides, faking IP address
|
||||
would imply sending IP packages with a made-up source address, and then you
|
||||
normally get a problem with intercepting the packages sent back as they
|
||||
would then not be routed to you!
|
||||
No. libcurl operates on a higher level. Besides, faking IP address would
|
||||
imply sending IP packet with a made-up source address, and then you normally
|
||||
get a problem with receiving the packet sent back as they would then not be
|
||||
routed to you!
|
||||
|
||||
If you use a proxy to access remote sites, the sites will not see your local
|
||||
IP address but instead the address of the proxy.
|
||||
|
||||
Also note that on many networks NATs or other IP-munging techniques are used
|
||||
that makes you see and use a different IP address locally than what the
|
||||
remote server will see you coming from.
|
||||
remote server will see you coming from. You may also consider using
|
||||
http://www.torproject.org .
|
||||
|
||||
5.13 How do I stop an ongoing transfer?
|
||||
|
||||
|
@@ -3,6 +3,9 @@ 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!
|
||||
|
||||
84. CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
|
||||
backends, so relying on this information in a generic app is flaky.
|
||||
|
||||
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
|
||||
@@ -24,18 +27,18 @@ may have been fixed since this was written!
|
||||
|
||||
80. Curl doesn't recognize certificates in DER format in keychain, but it
|
||||
works with PEM.
|
||||
http://curl.haxx.se/bug/view.cgi?id=3439999
|
||||
http://curl.haxx.se/bug/view.cgi?id=1065
|
||||
|
||||
79. SMTP. When sending data to multiple recipients, curl will abort and return
|
||||
failure if one of the recipients indicate failure (on the "RCPT TO"
|
||||
command). Ordinary mail programs would proceed and still send to the ones
|
||||
that can receive data. This is subject for change in the future.
|
||||
http://curl.haxx.se/bug/view.cgi?id=3438362
|
||||
http://curl.haxx.se/bug/view.cgi?id=1116
|
||||
|
||||
78. curl and libcurl don't always signal the client properly when "sending"
|
||||
zero bytes files - it makes for example the command line client not creating
|
||||
any file at all. Like when using FTP.
|
||||
http://curl.haxx.se/bug/view.cgi?id=3438362
|
||||
http://curl.haxx.se/bug/view.cgi?id=1063
|
||||
|
||||
77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it
|
||||
"abuses" the underlying connection re-use system and if connections are
|
||||
@@ -50,7 +53,7 @@ may have been fixed since this was written!
|
||||
properly if built with UNICODE defined together with the schannel/winssl
|
||||
backend. The original problem was mentioned in:
|
||||
http://curl.haxx.se/mail/lib-2009-10/0024.html
|
||||
http://curl.haxx.se/bug/view.cgi?id=2944325
|
||||
http://curl.haxx.se/bug/view.cgi?id=896
|
||||
|
||||
The schannel version verified to work as mentioned in
|
||||
http://curl.haxx.se/mail/lib-2012-07/0073.html
|
||||
@@ -60,7 +63,7 @@ may have been fixed since this was written!
|
||||
acknowledge the connection timeout during that phase but only the "real"
|
||||
timeout - which may surprise users as it is probably considered to be the
|
||||
connect phase to most people. Brought up (and is being misunderstood) in:
|
||||
http://curl.haxx.se/bug/view.cgi?id=2844077
|
||||
http://curl.haxx.se/bug/view.cgi?id=856
|
||||
|
||||
72. "Pausing pipeline problems."
|
||||
http://curl.haxx.se/mail/lib-2009-07/0214.html
|
||||
@@ -78,7 +81,7 @@ may have been fixed since this was written!
|
||||
http://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02
|
||||
|
||||
66. When using telnet, the time limitation options don't work.
|
||||
http://curl.haxx.se/bug/view.cgi?id=2818950
|
||||
http://curl.haxx.se/bug/view.cgi?id=846
|
||||
|
||||
65. When doing FTP over a socks proxy or CONNECT through HTTP proxy and the
|
||||
multi interface is used, libcurl will fail if the (passive) TCP connection
|
||||
@@ -109,7 +112,7 @@ may have been fixed since this was written!
|
||||
and instead the connection is "cancelled" (the operation is considered done)
|
||||
prematurely. There is a half-baked (busy-looping) patch provided in the bug
|
||||
report but it cannot be accepted as-is. See
|
||||
http://curl.haxx.se/bug/view.cgi?id=2006544
|
||||
http://curl.haxx.se/bug/view.cgi?id=748
|
||||
|
||||
55. libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's
|
||||
library header files exporting symbols/macros that should be kept private
|
||||
@@ -133,12 +136,12 @@ may have been fixed since this was written!
|
||||
protocol code. This should be very rare.
|
||||
|
||||
43. There seems to be a problem when connecting to the Microsoft telnet server.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1720605
|
||||
http://curl.haxx.se/bug/view.cgi?id=649
|
||||
|
||||
41. When doing an operation over FTP that requires the ACCT command (but not
|
||||
when logging in), the operation will fail since libcurl doesn't detect this
|
||||
and thus fails to issue the correct command:
|
||||
http://curl.haxx.se/bug/view.cgi?id=1693337
|
||||
http://curl.haxx.se/bug/view.cgi?id=635
|
||||
|
||||
39. Steffen Rumler's Race Condition in Curl_proxyCONNECT:
|
||||
http://curl.haxx.se/mail/lib-2007-01/0045.html
|
||||
@@ -151,7 +154,7 @@ may have been fixed since this was written!
|
||||
|
||||
34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts.
|
||||
Also see #12. According to bug #1556528, even the SOCKS5 connect code does
|
||||
not do it right: http://curl.haxx.se/bug/view.cgi?id=1556528,
|
||||
not do it right: http://curl.haxx.se/bug/view.cgi?id=604
|
||||
|
||||
31. "curl-config --libs" will include details set in LDFLAGS when configure is
|
||||
run that might be needed only for building libcurl. Further, curl-config
|
||||
@@ -166,13 +169,12 @@ may have been fixed since this was written!
|
||||
IDs in URLs to get around the problem of percent signs being
|
||||
special. According to the reporter, Firefox deals with the URL _with_ a
|
||||
percent letter (which seems like a blatant URL spec violation).
|
||||
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25).
|
||||
|
||||
See http://curl.haxx.se/bug/view.cgi?id=1371118
|
||||
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25):
|
||||
http://curl.haxx.se/bug/view.cgi?id=555
|
||||
|
||||
26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in
|
||||
"system context" will make it use wrong(?) user name - at least when compared
|
||||
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
|
||||
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=535
|
||||
|
||||
23. SOCKS-related problems:
|
||||
B) libcurl doesn't support FTPS over a SOCKS proxy.
|
||||
@@ -218,7 +220,7 @@ may have been fixed since this was written!
|
||||
10. To get HTTP Negotiate authentication to work fine, you need to provide a
|
||||
(fake) user name (this concerns both curl and the lib) because the code
|
||||
wrongly only considers authentication if there's a user name provided.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1004841. How?
|
||||
http://curl.haxx.se/bug/view.cgi?id=440 How?
|
||||
http://curl.haxx.se/mail/lib-2004-08/0182.html
|
||||
|
||||
8. Doing resumed upload over HTTP does not work with '-C -', because curl
|
||||
|
118
docs/curl.1
118
docs/curl.1
@@ -103,6 +103,18 @@ any response data to the terminal.
|
||||
If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your
|
||||
friend.
|
||||
.SH OPTIONS
|
||||
Options start with one or two dashes. Many of the options require an addition
|
||||
value next to it.
|
||||
|
||||
The short "single-dash" form of the options, -d for example, may be used with
|
||||
or without a space between it and its value, although a space is a recommended
|
||||
separator. The long "double-dash" form, --data for example, requires a space
|
||||
between it and its value.
|
||||
|
||||
Short version options that don't need any additional values can be used
|
||||
immediately next to each other, like for example you can specify all the
|
||||
options -O, -L and -v at once as -OLv.
|
||||
|
||||
In general, all boolean options are enabled with --\fBoption\fP and yet again
|
||||
disabled with --\fBno-\fPoption. That is, you use the exact same option name
|
||||
but prefix it with "no-". However, in this list we mostly only list and show
|
||||
@@ -113,8 +125,14 @@ same command line option.)
|
||||
Make curl display progress as a simple progress bar instead of the standard,
|
||||
more informational, meter.
|
||||
.IP "-0, --http1.0"
|
||||
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its
|
||||
internally preferred: HTTP 1.1.
|
||||
(HTTP) Tells curl to use HTTP version 1.0 instead of using its internally
|
||||
preferred: HTTP 1.1.
|
||||
.IP "--http1.1"
|
||||
(HTTP) Tells curl to use HTTP version 1.1. This is the internal default
|
||||
version. (Added in 7.33.0)
|
||||
.IP "--http2.0"
|
||||
(HTTP) Tells curl to issue its requests using HTTP 2.0. This requires that the
|
||||
underlying libcurl was built to support it. (Added in 7.33.0)
|
||||
.IP "-1, --tlsv1"
|
||||
(SSL)
|
||||
Forces curl to use TLS version 1 when negotiating with a remote TLS server.
|
||||
@@ -272,7 +290,8 @@ If you start the data with the letter @, the rest should be a file name to
|
||||
read the data from, or - if you want curl to read the data from stdin. The
|
||||
contents of the file must already be URL-encoded. Multiple files can also be
|
||||
specified. Posting data from a file named 'foobar' would thus be done with
|
||||
\fI--data @foobar\fP.
|
||||
\fI--data\fP @foobar. When --data is told to read from a file like that,
|
||||
carriage returns and newlines will be stripped out.
|
||||
.IP "-D, --dump-header <file>"
|
||||
Write the protocol headers to the specified file.
|
||||
|
||||
@@ -294,7 +313,7 @@ whatsoever.
|
||||
|
||||
If you start the data with the letter @, the rest should be a filename. Data
|
||||
is posted in a similar manner as \fI--data-ascii\fP does, except that newlines
|
||||
are preserved and conversions are never done.
|
||||
and carriage returns are preserved and conversions are never done.
|
||||
|
||||
If this option is used several times, the ones following the first will append
|
||||
data as described in \fI-d, --data\fP.
|
||||
@@ -369,6 +388,39 @@ is an alias for \fB--disable-epsv\fP.
|
||||
|
||||
Disabling EPSV only changes the passive behavior. If you want to switch to
|
||||
active mode you need to use \fI-P, --ftp-port\fP.
|
||||
.IP "--dns-interface <interface>"
|
||||
Tell curl to send outgoing DNS requests through <interface>. This option
|
||||
is a counterpart to \fI--interface\fP (which does not affect DNS). The
|
||||
supplied string must be an interface name (not an address).
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one. (Added in
|
||||
7.33.0)
|
||||
.IP "--dns-ipv4-addr <ip-address>"
|
||||
Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that
|
||||
the DNS requests originate from this address. The argument should be a
|
||||
single IPv4 address.
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one. (Added in
|
||||
7.33.0)
|
||||
.IP "--dns-ipv6-addr <ip-address>"
|
||||
Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that
|
||||
the DNS requests originate from this address. The argument should be a
|
||||
single IPv6 address.
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one. (Added in
|
||||
7.33.0)
|
||||
.IP "--dns-servers <ip-address,ip-address>"
|
||||
Set the list of DNS servers to be used instead of the system default.
|
||||
The list of IP addresses should be separated with commas. Port numbers
|
||||
may also optionally be given as \fI:<port-number>\fP after each IP
|
||||
address.
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one. (Added in
|
||||
7.33.0)
|
||||
.IP "-e, --referer <URL>"
|
||||
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also
|
||||
be set with the \fI-H, --header\fP flag of course. When used with
|
||||
@@ -380,7 +432,8 @@ If this option is used several times, the last one will be used.
|
||||
.IP "-E, --cert <certificate[:password]>"
|
||||
(SSL) Tells curl to use the specified client certificate file when getting a
|
||||
file with HTTPS, FTPS or another SSL-based protocol. The certificate must be
|
||||
in PEM format. If the optional password isn't specified, it will be queried
|
||||
in PKCS#12 format if using Secure Transport, or PEM format if using any other
|
||||
engine. If the optional password isn't specified, it will be queried
|
||||
for on the terminal. Note that this option assumes a \&"certificate" file that
|
||||
is the private key and the private certificate concatenated! See \fI--cert\fP
|
||||
and \fI--key\fP to specify them independently.
|
||||
@@ -396,9 +449,10 @@ 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.
|
||||
certificate string can either be the name of a certificate/private key in the
|
||||
system or user keychain, or the path to a PKCS#12-encoded certificate and
|
||||
private key. If you want to use a file from the current directory, please
|
||||
precede it with "./" prefix, in order to avoid confusion with a nickname.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "--engine <name>"
|
||||
@@ -1000,6 +1054,14 @@ you want the file saved in a different directory, make sure you change current
|
||||
working directory before you invoke curl with the \fB-O, --remote-name\fP flag!
|
||||
|
||||
You may use this option as many times as the number of URLs you have.
|
||||
.IP "--oauth2-bearer"
|
||||
(IMAP/POP3/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication.
|
||||
The Bearer Token is used in conjuction with the user name which can be
|
||||
specified as part of the \fI--url\fP or \fI-u, --user\fP options.
|
||||
|
||||
The Bearer Token and user name are formatted according to RFC 6750.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-p, --proxytunnel"
|
||||
When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP
|
||||
protocols to attempt to tunnel through the proxy instead of merely using it to
|
||||
@@ -1473,16 +1535,23 @@ If this option is used several times, the last one will be used.
|
||||
.IP "--trace-time"
|
||||
Prepends a time stamp to each trace or verbose line that curl displays.
|
||||
(Added in 7.14.0)
|
||||
.IP "-u, --user <user:password>"
|
||||
Specify the user name and password to use for server authentication. Overrides
|
||||
\fI-n, --netrc\fP and \fI--netrc-optional\fP.
|
||||
.IP "-u, --user <user:password;options>"
|
||||
Specify the user name, password and optional login options to use for server
|
||||
authentication. Overrides \fI-n, --netrc\fP and \fI--netrc-optional\fP.
|
||||
|
||||
If you just give the user name (without entering a colon) curl will prompt for
|
||||
a password.
|
||||
If you simply specify the user name, with or without the login options, curl
|
||||
will prompt for a password.
|
||||
|
||||
If you use an SSPI-enabled curl binary and do NTLM authentication, you can
|
||||
force curl to pick up the user name and password from your environment by
|
||||
simply specifying a single colon with this option: "-u :".
|
||||
If you use an SSPI-enabled curl binary and perform NTLM authentication, you
|
||||
can force curl to select the user name and password from your environment by
|
||||
simply specifying a single colon with this option: "-u :" or by specfying the
|
||||
login options on their own, for example "-u ;auth=NTLM".
|
||||
|
||||
You can use the optional login options part to specify protocol specific
|
||||
options that may be used during authentication. At present only IMAP, POP3 and
|
||||
SMTP support login options as part of the user login information. For more
|
||||
information about the login options please see RFC 2384, RFC 5092 and IETF
|
||||
draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-U, --proxy-user <user:password>"
|
||||
@@ -1643,8 +1712,16 @@ to follow location: headers.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>"
|
||||
Use the specified HTTP proxy. If the port number is not specified, it is
|
||||
assumed at port 1080.
|
||||
Use the specified proxy.
|
||||
|
||||
The proxy string can be specified with a protocol:// prefix to specify
|
||||
alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
|
||||
socks5h:// to request the specific SOCKS version to be used. No protocol
|
||||
specified, http:// and all others will be treated as HTTP proxies. (The
|
||||
protocol support was added in curl 7.21.7)
|
||||
|
||||
If the port number is not specified in the proxy string, it is assumed to be
|
||||
1080.
|
||||
|
||||
This option overrides existing environment variables that set the proxy to
|
||||
use. If there's an environment variable setting a proxy, you can set proxy to
|
||||
@@ -1663,11 +1740,6 @@ The proxy host can be specified the exact same way as the proxy environment
|
||||
variables, including the protocol prefix (http://) and the embedded user +
|
||||
password.
|
||||
|
||||
From 7.21.7, the proxy string may be specified with a protocol:// prefix to
|
||||
specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
|
||||
socks5h:// to request the specific SOCKS version to be used. No protocol
|
||||
specified, http:// and all others will be treated as HTTP proxies.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-X, --request <command>"
|
||||
(HTTP) Specifies a custom request method to use when communicating with the
|
||||
|
@@ -5,7 +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
|
||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget postinmemory
|
||||
|
||||
# These examples require external dependencies that may not be commonly
|
||||
# available on POSIX systems, so don't bother attempting to compile them here.
|
||||
|
@@ -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
|
||||
@@ -98,10 +98,6 @@ int main(void)
|
||||
* bytes big and contains the remote file.
|
||||
*
|
||||
* Do something nice with it!
|
||||
*
|
||||
* You should be aware of the fact that at this point we might have an
|
||||
* allocated data block, and nothing has yet deallocated that data. So when
|
||||
* you're done with it, you should free() it as a nice application.
|
||||
*/
|
||||
|
||||
printf("%lu bytes retrieved\n", (long)chunk.size);
|
||||
|
111
docs/examples/postinmemory.c
Normal file
111
docs/examples/postinmemory.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
struct MemoryStruct {
|
||||
char *memory;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static size_t
|
||||
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
||||
|
||||
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
|
||||
if(mem->memory == NULL) {
|
||||
/* out of memory! */
|
||||
printf("not enough memory (realloc returned NULL)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
||||
mem->size += realsize;
|
||||
mem->memory[mem->size] = 0;
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct MemoryStruct chunk;
|
||||
static const char *postthis="Field=1&Field=2&Field=3";
|
||||
|
||||
chunk.memory = malloc(1); /* will be grown as needed by realloc above */
|
||||
chunk.size = 0; /* no data at this point */
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.org/");
|
||||
|
||||
/* send all data to this function */
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
|
||||
/* we pass our 'chunk' struct to the callback function */
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||
|
||||
/* some servers don't like requests that are made without a user-agent
|
||||
field, so we provide one */
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
|
||||
|
||||
/* if we don't provide POSTFIELDSIZE, libcurl will strlen() by
|
||||
itself */
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
|
||||
|
||||
/* Perform the request, res will get the return code */
|
||||
res = curl_easy_perform(curl);
|
||||
/* Check for errors */
|
||||
if(res != CURLE_OK) {
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Now, our chunk.memory points to a memory block that is chunk.size
|
||||
* bytes big and contains the remote file.
|
||||
*
|
||||
* Do something nice with it!
|
||||
*/
|
||||
printf("%s\n",chunk.memory);
|
||||
}
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if(chunk.memory)
|
||||
free(chunk.memory);
|
||||
|
||||
/* we're done with libcurl, so clean it up */
|
||||
curl_global_cleanup();
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -38,8 +38,11 @@ that returns pause signals to the library that it couldn't take care of any
|
||||
data at all, and that data will then be delivered again to the callback when
|
||||
the writing is later unpaused.
|
||||
|
||||
NOTE: while it may feel tempting, take care and notice that you cannot call
|
||||
this function from another thread.
|
||||
While it may feel tempting, take care and notice that you cannot call this
|
||||
function from another thread. To unpause, you may for example call it from the
|
||||
progress callback (see \fIcurl_easy_setopt(3)\fP's
|
||||
\fICURLOPT_PROGRESSFUNCTION\fP), which gets called at least once per second,
|
||||
even if the connection is paused.
|
||||
|
||||
When this function is called to unpause reading, the chance is high that you
|
||||
will get your write callback called before this function returns.
|
||||
|
@@ -260,9 +260,9 @@ used to fast forward a file in a resumed upload (instead of reading all
|
||||
uploaded bytes with the normal read function/callback). It is also called to
|
||||
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
|
||||
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
|
||||
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
|
||||
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on
|
||||
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
|
||||
SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only
|
||||
passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1
|
||||
(CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
|
||||
(CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is
|
||||
free to work around the problem if possible. The latter can sometimes be done
|
||||
by instead reading from the input or similar.
|
||||
@@ -891,6 +891,19 @@ Active Directory server.
|
||||
For more information about the individual components of a LDAP URL please
|
||||
see RFC4516.
|
||||
|
||||
.B RTMP
|
||||
|
||||
There's no official URL spec for RTMP so libcurl uses the URL syntax supported
|
||||
by the underlying librtmp library. It has a syntax where it wants a
|
||||
traditional URL, followed by a space and a series of space-separated
|
||||
name=value pairs.
|
||||
|
||||
While space is not typically a "legal" letter, libcurl accepts them. When a
|
||||
user wants to pass in a '#' (hash) character it will be treated as a fragment
|
||||
and get cut off by libcurl if provided literally. You will instead have to
|
||||
escape it by providing it as backslash and its ASCII value in hexadecimal:
|
||||
"\\23".
|
||||
|
||||
.B NOTES
|
||||
|
||||
Starting with version 7.20.0, the fragment part of the URI will not be sent as
|
||||
@@ -1289,6 +1302,13 @@ mechanisms and to the IMAP, POP3 and SMTP protocols. (Added in 7.31.0)
|
||||
Note: Whilst IMAP supports this option there is no need to explicitly set it,
|
||||
as libcurl can determine the feature itself when the server supports the
|
||||
SASL-IR CAPABILITY.
|
||||
.IP CURLOPT_BEARER
|
||||
Pass a char * as parameter, which should point to the zero terminated OAUTH
|
||||
2.0 Bearer Access Token for use with IMAP. POP3 and SMTP servers that support
|
||||
the OAUTH 2.0 Authorization Framework. (Added in 7.33.0)
|
||||
|
||||
Note: The user name used to generate the Bearer Token should be supplied via
|
||||
the \fICURLOPT_USERNAME\fP option.
|
||||
.SH HTTP OPTIONS
|
||||
.IP CURLOPT_AUTOREFERER
|
||||
Pass a parameter set to 1 to enable this. When enabled, libcurl will
|
||||
@@ -2142,10 +2162,14 @@ In unix-like systems, this might cause signals to be used unless
|
||||
|
||||
Default timeout is 0 (zero) which means it never times out.
|
||||
.IP CURLOPT_TIMEOUT_MS
|
||||
Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If
|
||||
libcurl is built to use the standard system name resolver, that portion
|
||||
of the transfer will still use full-second resolution for timeouts with
|
||||
a minimum timeout allowed of one second.
|
||||
An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds
|
||||
instead. If libcurl is built to use the standard system name resolver, that
|
||||
portion of the transfer will still use full-second resolution for timeouts
|
||||
with a minimum timeout allowed of one second.
|
||||
|
||||
If both \fICURLOPT_TIMEOUT\fP and \fICURLOPT_TIMEOUT_MS\fP are set, the value
|
||||
set last will be used.
|
||||
|
||||
(Added in 7.16.2)
|
||||
.IP CURLOPT_LOW_SPEED_LIMIT
|
||||
Pass a long as parameter. It contains the transfer speed in bytes per second
|
||||
@@ -2291,6 +2315,36 @@ This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one.
|
||||
|
||||
(Added in 7.24.0)
|
||||
.IP CURLOPT_DNS_INTERFACE
|
||||
Pass a char * as parameter. Set the name of the network interface that
|
||||
the DNS resolver should bind to. This must be an interface name (not an
|
||||
address). Set this option to NULL to use the default setting (don't
|
||||
bind to a specific interface).
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one.
|
||||
|
||||
(Added in 7.33.0)
|
||||
.IP CURLOPT_DNS_LOCAL_IP4
|
||||
Set the local IPv4 address that the resolver should bind to. The argument
|
||||
should be of type char * and contain a single IPv4 address as a string.
|
||||
Set this option to NULL to use the default setting (don't
|
||||
bind to a specific IP address).
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one.
|
||||
|
||||
(Added in 7.33.0)
|
||||
.IP CURLOPT_DNS_LOCAL_IP6
|
||||
Set the local IPv6 address that the resolver should bind to. The argument
|
||||
should be of type char * and contain a single IPv6 address as a string.
|
||||
Set this option to NULL to use the default setting (don't
|
||||
bind to a specific IP address).
|
||||
|
||||
This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one.
|
||||
|
||||
(Added in 7.33.0)
|
||||
.IP CURLOPT_ACCEPTTIMEOUT_MS
|
||||
Pass a long telling libcurl the maximum number of milliseconds to wait for a
|
||||
server to connect back to libcurl when an active FTP connection is used. If no
|
||||
@@ -2298,22 +2352,20 @@ timeout is set, the internal default of 60000 will be used. (Added in 7.24.0)
|
||||
.SH SSL and SECURITY OPTIONS
|
||||
.IP CURLOPT_SSLCERT
|
||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||
the file name of your certificate. The default format is "PEM" and can be
|
||||
changed with \fICURLOPT_SSLCERTTYPE\fP.
|
||||
the file name of your certificate. The default format is "P12" on Secure
|
||||
Transport and "PEM" on other engines, and can be changed with
|
||||
\fICURLOPT_SSLCERTTYPE\fP.
|
||||
|
||||
With NSS this can also be the nickname of the certificate you wish to
|
||||
authenticate with. If you want to use a file from the current directory, please
|
||||
precede it with "./" prefix, in order to avoid confusion with a nickname.
|
||||
|
||||
(iOS and Mac OS X only) With Secure Transport, this string must match the name
|
||||
of a certificate that's in the system or user keychain. You should encode this
|
||||
string in UTF-8 format in case it contains non-ASCII characters. The private
|
||||
key corresponding to the certificate, and certificate chain (if any), must
|
||||
also be present in the keychain. (Added in 7.31.0)
|
||||
With NSS or Secure Transport, this can also be the nickname of the certificate
|
||||
you wish to authenticate with as it is named in the security database. If you
|
||||
want to use a file from the current directory, please precede it with "./"
|
||||
prefix, in order to avoid confusion with a nickname.
|
||||
.IP CURLOPT_SSLCERTTYPE
|
||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||
the format of your certificate. Supported formats are "PEM" and "DER". (Added
|
||||
in 7.9.3)
|
||||
the format of your certificate. Supported formats are "PEM" and "DER", except
|
||||
with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
|
||||
(on iOS 5 or later, or OS X 10.6 or later) also support "P12" for
|
||||
PKCS#12-encoded files. (Added in 7.9.3)
|
||||
.IP CURLOPT_SSLKEY
|
||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||
the file name of your private key. The default format is "PEM" and can be
|
||||
@@ -2321,7 +2373,7 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
|
||||
|
||||
(iOS and Mac OS X only) This option is ignored if curl was built against Secure
|
||||
Transport. Secure Transport expects the private key to be already present in
|
||||
the keychain containing the certificate.
|
||||
the keychain or PKCS#12 file containing the certificate.
|
||||
.IP CURLOPT_SSLKEYTYPE
|
||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
||||
|
@@ -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
|
||||
@@ -273,6 +273,9 @@ The passed-in socket is not a valid one that libcurl already knows about.
|
||||
.IP "CURLM_UNKNOWN_OPTION (6)"
|
||||
curl_multi_setopt() with unsupported option
|
||||
(Added in 7.15.4)
|
||||
.IP "CURLM_ADDED_ALREADY (7)"
|
||||
An easy handle already added to a multi handle was attempted to get added a
|
||||
second time. (Added in 7.32.1)
|
||||
.SH "CURLSHcode"
|
||||
The "share" interface will return a CURLSHcode to indicate when an error has
|
||||
occurred. Also consider \fIcurl_share_strerror(3)\fP.
|
||||
|
@@ -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
|
||||
@@ -39,8 +39,15 @@ maintain while using libcurl. This essentially means you call
|
||||
for details.
|
||||
|
||||
To transfer files, you always set up an "easy handle" using
|
||||
\fIcurl_easy_init(3)\fP, but when you want the file(s) transferred you have
|
||||
the option of using the "easy" interface, or the "multi" interface.
|
||||
\fIcurl_easy_init(3)\fP for a single specific transfer (in either
|
||||
direction). You then set your desired set of options in that handle with
|
||||
\fIcurk_easy_setopt(3)\fP. Options you set with \fIcurl_easy_setopt(3)\fP will
|
||||
be used on every repeated use of this handle until you either call the
|
||||
function again and change the option, or you reset them all with
|
||||
\fIcurl_easy_reset(3)\fP.
|
||||
|
||||
To actually transfer data you have the option of using the "easy" interface,
|
||||
or the "multi" interface.
|
||||
|
||||
The easy interface is a synchronous interface with which you call
|
||||
\fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is
|
||||
@@ -51,7 +58,8 @@ The multi interface on the other hand is an asynchronous interface, that you
|
||||
call and that performs only a little piece of the transfer on each invoke. It
|
||||
is perfect if you want to do things while the transfer is in progress, or
|
||||
similar. The multi interface allows you to select() on libcurl action, and
|
||||
even to easily download multiple files simultaneously using a single thread. See further details in the \fIlibcurl-multi(3)\fP man page.
|
||||
even to easily download multiple files simultaneously using a single
|
||||
thread. See further details in the \fIlibcurl-multi(3)\fP man page.
|
||||
|
||||
You can have multiple easy handles share certain data, even if they are used
|
||||
in different threads. This magic is setup using the share interface, as
|
||||
@@ -115,19 +123,21 @@ Persistent connections means that libcurl can re-use the same connection for
|
||||
several transfers, if the conditions are right.
|
||||
|
||||
libcurl will \fBalways\fP attempt to use persistent connections. Whenever you
|
||||
use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP, libcurl will
|
||||
attempt to use an existing connection to do the transfer, and if none exists
|
||||
it'll open a new one that will be subject for re-use on a possible following
|
||||
call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
|
||||
use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl
|
||||
will attempt to use an existing connection to do the transfer, and if none
|
||||
exists it'll open a new one that will be subject for re-use on a possible
|
||||
following call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
|
||||
|
||||
To allow libcurl to take full advantage of persistent connections, you should
|
||||
do as many of your file transfers as possible using the same curl handle. When
|
||||
you call \fIcurl_easy_cleanup(3)\fP, all the possibly open connections held by
|
||||
libcurl will be closed and forgotten.
|
||||
do as many of your file transfers as possible using the same handle.
|
||||
|
||||
Note that the options set with \fIcurl_easy_setopt(3)\fP will be used on
|
||||
every repeated \fIcurl_easy_perform(3)\fP call.
|
||||
If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all
|
||||
the possibly open connections held by libcurl will be closed and forgotten.
|
||||
|
||||
When you've created a multi handle and are using the multi interface, the
|
||||
connection pool is instead kept in the multi handle so closing and creating
|
||||
new easy handles to do transfers will not affect them. Instead all added easy
|
||||
handles can take advantage of the single shared pool.
|
||||
.SH "GLOBAL CONSTANTS"
|
||||
There are a variety of constants that libcurl uses, mainly through its
|
||||
internal use of other libraries, which are too complicated for the
|
||||
|
@@ -85,8 +85,8 @@ CURLE_LDAP_SEARCH_FAILED 7.1
|
||||
CURLE_LIBRARY_NOT_FOUND 7.1 7.17.0
|
||||
CURLE_LOGIN_DENIED 7.13.1
|
||||
CURLE_MALFORMAT_USER 7.1 7.17.0
|
||||
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
|
||||
CURLE_NOT_BUILT_IN 7.21.5
|
||||
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
|
||||
CURLE_OK 7.1
|
||||
CURLE_OPERATION_TIMEDOUT 7.10.2
|
||||
CURLE_OPERATION_TIMEOUTED 7.1 7.17.0
|
||||
@@ -270,10 +270,10 @@ CURLKHTYPE_RSA1 7.19.6
|
||||
CURLKHTYPE_UNKNOWN 7.19.6
|
||||
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0
|
||||
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0
|
||||
CURLMOPT_MAXCONNECTS 7.16.3
|
||||
CURLMOPT_MAX_HOST_CONNECTIONS 7.30.0
|
||||
CURLMOPT_MAX_PIPELINE_LENGTH 7.30.0
|
||||
CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0
|
||||
CURLMOPT_MAXCONNECTS 7.16.3
|
||||
CURLMOPT_PIPELINING 7.16.0
|
||||
CURLMOPT_PIPELINING_SERVER_BL 7.30.0
|
||||
CURLMOPT_PIPELINING_SITE_BL 7.30.0
|
||||
@@ -283,6 +283,7 @@ CURLMOPT_TIMERDATA 7.16.0
|
||||
CURLMOPT_TIMERFUNCTION 7.16.0
|
||||
CURLMSG_DONE 7.9.6
|
||||
CURLMSG_NONE 7.9.6
|
||||
CURLM_ADDED_ALREADY 7.32.1
|
||||
CURLM_BAD_EASY_HANDLE 7.9.6
|
||||
CURLM_BAD_HANDLE 7.9.6
|
||||
CURLM_BAD_SOCKET 7.15.4
|
||||
@@ -331,6 +332,9 @@ CURLOPT_DEBUGDATA 7.9.6
|
||||
CURLOPT_DEBUGFUNCTION 7.9.6
|
||||
CURLOPT_DIRLISTONLY 7.17.0
|
||||
CURLOPT_DNS_CACHE_TIMEOUT 7.9.3
|
||||
CURLOPT_DNS_INTERFACE 7.33.0
|
||||
CURLOPT_DNS_LOCAL_IP4 7.33.0
|
||||
CURLOPT_DNS_LOCAL_IP6 7.33.0
|
||||
CURLOPT_DNS_SERVERS 7.24.0
|
||||
CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
|
||||
CURLOPT_EGDSOCKET 7.7
|
||||
@@ -527,6 +531,7 @@ CURLOPT_WRITEHEADER 7.1
|
||||
CURLOPT_WRITEINFO 7.1
|
||||
CURLOPT_XFERINFODATA 7.32.0
|
||||
CURLOPT_XFERINFOFUNCTION 7.32.0
|
||||
CURLOPT_XOAUTH2_BEARER 7.33.0
|
||||
CURLPAUSE_ALL 7.18.0
|
||||
CURLPAUSE_CONT 7.18.0
|
||||
CURLPAUSE_RECV 7.18.0
|
||||
@@ -620,14 +625,15 @@ CURL_FORMADD_NULL 7.9.8
|
||||
CURL_FORMADD_OK 7.9.8
|
||||
CURL_FORMADD_OPTION_TWICE 7.9.8
|
||||
CURL_FORMADD_UNKNOWN_OPTION 7.9.8
|
||||
CURL_GLOBAL_ACK_EINTR 7.30.0
|
||||
CURL_GLOBAL_ALL 7.8
|
||||
CURL_GLOBAL_DEFAULT 7.8
|
||||
CURL_GLOBAL_NOTHING 7.8
|
||||
CURL_GLOBAL_SSL 7.8
|
||||
CURL_GLOBAL_WIN32 7.8.1
|
||||
CURL_GLOBAL_ACK_EINTR 7.30.0
|
||||
CURL_HTTP_VERSION_1_0 7.9.1
|
||||
CURL_HTTP_VERSION_1_1 7.9.1
|
||||
CURL_HTTP_VERSION_2_0 7.33.0
|
||||
CURL_HTTP_VERSION_NONE 7.9.1
|
||||
CURL_IPRESOLVE_V4 7.10.8
|
||||
CURL_IPRESOLVE_V6 7.10.8
|
||||
@@ -700,6 +706,7 @@ CURL_VERSION_CONV 7.15.4
|
||||
CURL_VERSION_CURLDEBUG 7.19.6
|
||||
CURL_VERSION_DEBUG 7.10.6
|
||||
CURL_VERSION_GSSNEGOTIATE 7.10.6
|
||||
CURL_VERSION_HTTP2 7.33.0
|
||||
CURL_VERSION_IDN 7.12.0
|
||||
CURL_VERSION_IPV6 7.10
|
||||
CURL_VERSION_KERBEROS4 7.10
|
||||
|
@@ -645,16 +645,18 @@ typedef enum {
|
||||
|
||||
#define CURL_ERROR_SIZE 256
|
||||
|
||||
struct curl_khkey {
|
||||
const char *key; /* points to a zero-terminated string encoded with base64
|
||||
if len is zero, otherwise to the "raw" data */
|
||||
size_t len;
|
||||
enum type {
|
||||
enum curl_khtype {
|
||||
CURLKHTYPE_UNKNOWN,
|
||||
CURLKHTYPE_RSA1,
|
||||
CURLKHTYPE_RSA,
|
||||
CURLKHTYPE_DSS
|
||||
} keytype;
|
||||
};
|
||||
|
||||
struct curl_khkey {
|
||||
const char *key; /* points to a zero-terminated string encoded with base64
|
||||
if len is zero, otherwise to the "raw" data */
|
||||
size_t len;
|
||||
enum curl_khtype keytype;
|
||||
};
|
||||
|
||||
/* this is the set of return values expected from the curl_sshkeycallback
|
||||
@@ -1551,6 +1553,22 @@ typedef enum {
|
||||
* prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
|
||||
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
|
||||
|
||||
/* The XOAUTH2 bearer token */
|
||||
CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
|
||||
|
||||
/* Set the interface string to use as outgoing network
|
||||
* interface for DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
|
||||
|
||||
/* Set the local IPv4 address to use for outgoing DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
|
||||
|
||||
/* Set the local IPv4 address to use for outgoing DNS requests.
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1603,6 +1621,7 @@ enum {
|
||||
for us! */
|
||||
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
|
||||
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
||||
CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
|
||||
|
||||
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
||||
};
|
||||
@@ -2166,6 +2185,7 @@ typedef struct {
|
||||
#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
|
||||
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
|
||||
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
|
||||
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
|
||||
|
||||
/*
|
||||
* NAME curl_version_info()
|
||||
|
@@ -30,12 +30,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.32.0-DEV"
|
||||
#define LIBCURL_VERSION "7.33.0-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 32
|
||||
#define LIBCURL_VERSION_MINOR 33
|
||||
#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 0x072000
|
||||
#define LIBCURL_VERSION_NUM 0x072100
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
@@ -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
|
||||
@@ -64,6 +64,8 @@ typedef enum {
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||
attempted to get added - again */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
|
@@ -264,6 +264,11 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
(option) == CURLOPT_RTSP_SESSION_ID || \
|
||||
(option) == CURLOPT_RTSP_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
(option) == CURLOPT_DNS_SERVERS || \
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
|
@@ -10,7 +10,7 @@
|
||||
CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
|
||||
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
|
||||
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
|
||||
netrc.c getinfo.c transfer.c strequal.c easy.c security.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 \
|
||||
@@ -26,12 +26,12 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.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 dotdot.c x509asn1.c \
|
||||
gskit.c
|
||||
gskit.c http2.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 \
|
||||
getinfo.h strequal.h curl_sec.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 \
|
||||
@@ -45,4 +45,5 @@ 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 dotdot.h x509asn1.h gskit.h
|
||||
multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h \
|
||||
http2.h
|
||||
|
@@ -566,7 +566,6 @@ X_OBJS= \
|
||||
$(DIROBJ)\imap.obj \
|
||||
$(DIROBJ)\inet_ntop.obj \
|
||||
$(DIROBJ)\inet_pton.obj \
|
||||
$(DIROBJ)\krb4.obj \
|
||||
$(DIROBJ)\krb5.obj \
|
||||
$(DIROBJ)\ldap.obj \
|
||||
$(DIROBJ)\llist.obj \
|
||||
|
31
lib/README.http2
Normal file
31
lib/README.http2
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
HTTP2 with libcurl
|
||||
|
||||
Spec: http://tools.ietf.org/html/draft-ietf-httpbis-http2-06
|
||||
|
||||
nghttp2 (https://github.com/tatsuhiro-t/nghttp2)
|
||||
|
||||
We're depending on this 3rd party library for the actual low level protocol
|
||||
handling parts. The reason for this is that HTTP2 is much more complex at
|
||||
that layer than HTTP1.1 (which we implement on our own) and that nghttp2 is
|
||||
an already existing and well functional library.
|
||||
|
||||
Over an http:// URL
|
||||
|
||||
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will include
|
||||
an upgrade header in the initial request to the host to allow upgrading to
|
||||
http2. Possibly introduce an option that will cause libcurl to fail if not
|
||||
possible to upgrade. Possibly introduce an option that makes libcurl use
|
||||
http2 at once over http://
|
||||
|
||||
Over an https:// URL
|
||||
|
||||
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will use ALPN
|
||||
(or NPN) to negotiate which protocol to continue with. Possibly introduce an
|
||||
option that will cause libcurl to fail if not possible to use http2.
|
||||
|
||||
To consider:
|
||||
|
||||
- How to tell libcurl when using the multi interface that all or some of the
|
||||
handles are allowed to re-use the same physical connection. Can we just
|
||||
re-use existing pipelining logic?
|
@@ -623,4 +623,72 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
|
||||
const char *interf)
|
||||
{
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
if(!interf)
|
||||
interf = "";
|
||||
|
||||
ares_set_local_dev((ares_channel)data->state.resolver, interf);
|
||||
|
||||
return CURLE_OK;
|
||||
#else /* c-ares version too old! */
|
||||
(void)data;
|
||||
(void)interf;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
||||
const char *local_ip4)
|
||||
{
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
uint32_t a4;
|
||||
|
||||
if((!local_ip4) || (local_ip4[0] == 0)) {
|
||||
a4 = 0; /* disabled: do not bind to a specific address */
|
||||
}
|
||||
else {
|
||||
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4));
|
||||
|
||||
return CURLE_OK;
|
||||
#else /* c-ares version too old! */
|
||||
(void)data;
|
||||
(void)local_ip4;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
||||
const char *local_ip6)
|
||||
{
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
unsigned char a6[INET6_ADDRSTRLEN];
|
||||
|
||||
if((!local_ip6) || (local_ip6[0] == 0)) {
|
||||
/* disabled: do not bind to a specific address */
|
||||
memset(a6, 0, sizeof(a6));
|
||||
}
|
||||
else {
|
||||
if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
ares_set_local_ip6((ares_channel)data->state.resolver, a6);
|
||||
|
||||
return CURLE_OK;
|
||||
#else /* c-ares version too old! */
|
||||
(void)data;
|
||||
(void)local_ip6;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
#endif /* CURLRES_ARES */
|
||||
|
@@ -265,7 +265,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
|
||||
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
|
||||
{
|
||||
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
|
||||
char service [NI_MAXSERV];
|
||||
char service[12];
|
||||
int rc;
|
||||
|
||||
snprintf(service, sizeof(service), "%d", tsd->port);
|
||||
@@ -559,7 +559,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
struct in_addr in;
|
||||
Curl_addrinfo *res;
|
||||
int error;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
int pf = PF_INET;
|
||||
#ifdef CURLRES_IPV6
|
||||
struct in6_addr in6;
|
||||
@@ -635,4 +635,28 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
|
||||
const char *interf)
|
||||
{
|
||||
(void)data;
|
||||
(void)interf;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
||||
const char *local_ip4)
|
||||
{
|
||||
(void)data;
|
||||
(void)local_ip4;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
||||
const char *local_ip6)
|
||||
{
|
||||
(void)data;
|
||||
(void)local_ip6;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
#endif /* CURLRES_THREADED */
|
||||
|
@@ -390,21 +390,6 @@
|
||||
# define SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* STRUCT RELATED */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define if you have struct sockaddr_storage. */
|
||||
#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
#endif
|
||||
|
||||
/* Define if you have struct timeval. */
|
||||
#define HAVE_STRUCT_TIMEVAL 1
|
||||
|
||||
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
|
||||
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* BSD-style lwIP TCP/IP stack SPECIFIC */
|
||||
/* ---------------------------------------------------------------- */
|
||||
@@ -572,6 +557,25 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* STRUCT RELATED */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define if you have struct sockaddr_storage. */
|
||||
#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
#endif
|
||||
|
||||
/* Define if you have struct timeval. */
|
||||
#define HAVE_STRUCT_TIMEVAL 1
|
||||
|
||||
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
|
||||
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
|
||||
|
||||
#if HAVE_WINSOCK2_H && defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
#define HAVE_STRUCT_POLLFD 1
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* LARGE FILE SUPPORT */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
37
lib/cookie.c
37
lib/cookie.c
@@ -290,6 +290,34 @@ static void strstore(char **str, const char *newstr)
|
||||
*str = strdup(newstr);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_expired() removes expired cookies.
|
||||
*/
|
||||
static void remove_expired(struct CookieInfo *cookies)
|
||||
{
|
||||
struct Cookie *co, *nx, *pv;
|
||||
curl_off_t now = (curl_off_t)time(NULL);
|
||||
|
||||
co = cookies->cookies;
|
||||
pv = NULL;
|
||||
while(co) {
|
||||
nx = co->next;
|
||||
if((co->expirestr || co->maxage) && co->expires < now) {
|
||||
if(co == cookies->cookies) {
|
||||
cookies->cookies = co->next;
|
||||
}
|
||||
else {
|
||||
pv->next = co->next;
|
||||
}
|
||||
cookies->numcookies--;
|
||||
freecookie(co);
|
||||
}
|
||||
else {
|
||||
pv = co;
|
||||
}
|
||||
co = nx;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
@@ -700,6 +728,9 @@ Curl_cookie_add(struct SessionHandle *data,
|
||||
superceeds an already existing cookie, which it may if the previous have
|
||||
the same domain and path as this */
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
clist = c->cookies;
|
||||
replace_old = FALSE;
|
||||
while(clist) {
|
||||
@@ -931,6 +962,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
if(!c || !c->cookies)
|
||||
return NULL; /* no cookie struct or no cookies in the struct */
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
co = c->cookies;
|
||||
|
||||
while(co) {
|
||||
@@ -1173,6 +1207,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
destination file */
|
||||
return 0;
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
if(strequal("-", dumphere)) {
|
||||
/* use stdout */
|
||||
out = stdout;
|
||||
|
@@ -52,12 +52,14 @@
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
|
||||
|
||||
#define CURL_BUILD_IOS 0
|
||||
#define CURL_BUILD_IOS_7 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
|
||||
#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
|
||||
/* 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
|
||||
@@ -66,9 +68,11 @@
|
||||
#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
|
||||
#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
|
||||
|
||||
#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
|
||||
#define CURL_BUILD_IOS 1
|
||||
#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
|
||||
#define CURL_BUILD_MAC 0
|
||||
#define CURL_BUILD_MAC_10_5 0
|
||||
#define CURL_BUILD_MAC_10_6 0
|
||||
@@ -660,6 +664,110 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
|
||||
return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
|
||||
break;
|
||||
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
|
||||
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
|
||||
/* TLS PSK (RFC 4279): */
|
||||
case TLS_PSK_WITH_RC4_128_SHA:
|
||||
return "TLS_PSK_WITH_RC4_128_SHA";
|
||||
break;
|
||||
case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
|
||||
return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
|
||||
break;
|
||||
case TLS_PSK_WITH_AES_128_CBC_SHA:
|
||||
return "TLS_PSK_WITH_AES_128_CBC_SHA";
|
||||
break;
|
||||
case TLS_PSK_WITH_AES_256_CBC_SHA:
|
||||
return "TLS_PSK_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_RC4_128_SHA:
|
||||
return "TLS_DHE_PSK_WITH_RC4_128_SHA";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
|
||||
return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
|
||||
return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
|
||||
return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_RC4_128_SHA:
|
||||
return "TLS_RSA_PSK_WITH_RC4_128_SHA";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
|
||||
return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
|
||||
return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
|
||||
return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
|
||||
break;
|
||||
/* More TLS PSK (RFC 4785): */
|
||||
case TLS_PSK_WITH_NULL_SHA:
|
||||
return "TLS_PSK_WITH_NULL_SHA";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_NULL_SHA:
|
||||
return "TLS_DHE_PSK_WITH_NULL_SHA";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_NULL_SHA:
|
||||
return "TLS_RSA_PSK_WITH_NULL_SHA";
|
||||
break;
|
||||
/* Even more TLS PSK (RFC 5487): */
|
||||
case TLS_PSK_WITH_AES_128_GCM_SHA256:
|
||||
return "TLS_PSK_WITH_AES_128_GCM_SHA256";
|
||||
break;
|
||||
case TLS_PSK_WITH_AES_256_GCM_SHA384:
|
||||
return "TLS_PSK_WITH_AES_256_GCM_SHA384";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
|
||||
return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
|
||||
return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
|
||||
return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
|
||||
return "TLS_PSK_WITH_AES_256_GCM_SHA384";
|
||||
break;
|
||||
case TLS_PSK_WITH_AES_128_CBC_SHA256:
|
||||
return "TLS_PSK_WITH_AES_128_CBC_SHA256";
|
||||
break;
|
||||
case TLS_PSK_WITH_AES_256_CBC_SHA384:
|
||||
return "TLS_PSK_WITH_AES_256_CBC_SHA384";
|
||||
break;
|
||||
case TLS_PSK_WITH_NULL_SHA256:
|
||||
return "TLS_PSK_WITH_NULL_SHA256";
|
||||
break;
|
||||
case TLS_PSK_WITH_NULL_SHA384:
|
||||
return "TLS_PSK_WITH_NULL_SHA384";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
|
||||
return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
|
||||
return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_NULL_SHA256:
|
||||
return "TLS_DHE_PSK_WITH_NULL_SHA256";
|
||||
break;
|
||||
case TLS_DHE_PSK_WITH_NULL_SHA384:
|
||||
return "TLS_RSA_PSK_WITH_NULL_SHA384";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
|
||||
return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
|
||||
return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_NULL_SHA256:
|
||||
return "TLS_RSA_PSK_WITH_NULL_SHA256";
|
||||
break;
|
||||
case TLS_RSA_PSK_WITH_NULL_SHA384:
|
||||
return "TLS_RSA_PSK_WITH_NULL_SHA384";
|
||||
break;
|
||||
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
|
||||
}
|
||||
return "TLS_NULL_WITH_NULL_NULL";
|
||||
}
|
||||
@@ -819,6 +927,68 @@ static OSStatus CopyIdentityWithLabel(char *label,
|
||||
return status;
|
||||
}
|
||||
|
||||
static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
|
||||
const char *cPassword,
|
||||
SecIdentityRef *out_cert_and_key)
|
||||
{
|
||||
OSStatus status = errSecItemNotFound;
|
||||
CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
|
||||
(const UInt8 *)cPath, strlen(cPath), false);
|
||||
CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
|
||||
cPassword, kCFStringEncodingUTF8) : NULL;
|
||||
CFDataRef pkcs_data = NULL;
|
||||
|
||||
/* We can import P12 files on iOS or OS X 10.6 or later: */
|
||||
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
|
||||
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
|
||||
NULL, NULL, &status)) {
|
||||
const void *cKeys[] = {kSecImportExportPassphrase};
|
||||
const void *cValues[] = {password};
|
||||
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
|
||||
password ? 1L : 0L, NULL, NULL);
|
||||
CFArrayRef items = NULL;
|
||||
|
||||
/* Here we go: */
|
||||
status = SecPKCS12Import(pkcs_data, options, &items);
|
||||
if(status == noErr) {
|
||||
CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
|
||||
const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
|
||||
kSecImportItemIdentity);
|
||||
|
||||
/* Retain the identity; we don't care about any other data... */
|
||||
CFRetain(temp_identity);
|
||||
*out_cert_and_key = (SecIdentityRef)temp_identity;
|
||||
CFRelease(items);
|
||||
}
|
||||
CFRelease(options);
|
||||
CFRelease(pkcs_data);
|
||||
}
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
if(password)
|
||||
CFRelease(password);
|
||||
CFRelease(pkcs_url);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This code was borrowed from nss.c, with some modifications:
|
||||
* Determine whether the nickname passed in is a filename that needs to
|
||||
* be loaded as a PEM or a regular NSS nickname.
|
||||
*
|
||||
* returns 1 for a file
|
||||
* returns 0 for not a file
|
||||
*/
|
||||
CF_INLINE bool is_file(const char *filename)
|
||||
{
|
||||
struct_stat st;
|
||||
|
||||
if(filename == NULL)
|
||||
return false;
|
||||
|
||||
if(stat(filename, &st) == 0)
|
||||
return S_ISREG(st.st_mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
@@ -988,9 +1158,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
SecIdentityRef cert_and_key = NULL;
|
||||
bool is_cert_file = is_file(data->set.str[STRING_CERT]);
|
||||
|
||||
/* User wants to authenticate with a client cert. Look for it: */
|
||||
/* User wants to authenticate with a client cert. Look for it:
|
||||
If we detect that this is a file on disk, then let's load it.
|
||||
Otherwise, assume that the user wants to use an identity loaded
|
||||
from the Keychain. */
|
||||
if(is_cert_file) {
|
||||
if(!data->set.str[STRING_CERT_TYPE])
|
||||
infof(data, "WARNING: SSL: Certificate type not set, assuming "
|
||||
"PKCS#12 format.\n");
|
||||
else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
|
||||
strlen(data->set.str[STRING_CERT_TYPE])) != 0)
|
||||
infof(data, "WARNING: SSL: The Security framework only supports "
|
||||
"loading identities that are in PKCS#12 format.\n");
|
||||
|
||||
err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
|
||||
data->set.str[STRING_KEY_PASSWD], &cert_and_key);
|
||||
}
|
||||
else
|
||||
err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
|
||||
|
||||
if(err == noErr) {
|
||||
SecCertificateRef cert = NULL;
|
||||
CFTypeRef certs_c[1];
|
||||
@@ -1027,8 +1215,29 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
CFRelease(cert_and_key);
|
||||
}
|
||||
else {
|
||||
failf(data, "SSL: Can't find the certificate \"%s\" and its private key "
|
||||
"in the Keychain.", data->set.str[STRING_CERT]);
|
||||
switch(err) {
|
||||
case errSecPkcs12VerifyFailure: case errSecAuthFailed:
|
||||
failf(data, "SSL: Incorrect password for the certificate \"%s\" "
|
||||
"and its private key.", data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case errSecDecode: case errSecUnknownFormat:
|
||||
failf(data, "SSL: Couldn't make sense of the data in the "
|
||||
"certificate \"%s\" and its private key.",
|
||||
data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case errSecPassphraseRequired:
|
||||
failf(data, "SSL The certificate \"%s\" requires a password.",
|
||||
data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case errSecItemNotFound:
|
||||
failf(data, "SSL: Can't find the certificate \"%s\" and its private "
|
||||
"key in the Keychain.", data->set.str[STRING_CERT]);
|
||||
break;
|
||||
default:
|
||||
failf(data, "SSL: Can't load the certificate \"%s\" and its private "
|
||||
"key: OSStatus %d", data->set.str[STRING_CERT], err);
|
||||
break;
|
||||
}
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
@@ -1121,11 +1330,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
case SSL_NULL_WITH_NULL_NULL:
|
||||
case SSL_RSA_WITH_NULL_MD5:
|
||||
case SSL_RSA_WITH_NULL_SHA:
|
||||
case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
|
||||
case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
|
||||
case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
|
||||
case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
|
||||
case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
|
||||
case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
|
||||
case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
|
||||
case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
|
||||
case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
|
||||
case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
|
||||
case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
|
||||
case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
|
||||
case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
|
||||
/* Disable anonymous ciphersuites: */
|
||||
case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
|
||||
case SSL_DH_anon_WITH_RC4_128_MD5:
|
||||
@@ -1181,6 +1400,13 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
Curl_safefree(all_ciphers);
|
||||
Curl_safefree(allowed_ciphers);
|
||||
|
||||
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
|
||||
/* We want to enable 1/n-1 when using a CBC cipher unless the user
|
||||
specifically doesn't want us doing that: */
|
||||
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
|
||||
!data->set.ssl_enable_beast);
|
||||
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
|
||||
|
||||
/* Check if there's a cached ID we can/should use here! */
|
||||
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
|
||||
&ssl_sessionid_len)) {
|
||||
|
@@ -22,6 +22,7 @@
|
||||
* RFC2831 DIGEST-MD5 authentication
|
||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
@@ -94,18 +95,18 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||
const char *passwdp,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
|
||||
CURLcode result;
|
||||
char *plainauth;
|
||||
size_t ulen;
|
||||
size_t plen;
|
||||
|
||||
ulen = strlen(userp);
|
||||
plen = strlen(passwdp);
|
||||
|
||||
if(2 * ulen + plen + 2 > sizeof(plainauth)) {
|
||||
plainauth = malloc(2 * ulen + plen + 2);
|
||||
if(!plainauth) {
|
||||
*outlen = 0;
|
||||
*outptr = NULL;
|
||||
|
||||
/* Plainauth too small */
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -117,8 +118,10 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||
memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
|
||||
result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
|
||||
outlen);
|
||||
Curl_safefree(plainauth);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,7 +193,7 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
size_t chlglen = 0;
|
||||
HMAC_context *ctxt;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char response[MAX_CURL_USER_LENGTH + 2 * MD5_DIGEST_LEN + 1];
|
||||
char *response;
|
||||
|
||||
/* Decode the challenge if necessary */
|
||||
if(chlg64len && *chlg64 != '=') {
|
||||
@@ -220,14 +223,19 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
Curl_HMAC_final(ctxt, digest);
|
||||
|
||||
/* Prepare the response */
|
||||
snprintf(response, sizeof(response),
|
||||
response = aprintf(
|
||||
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
userp, digest[0], digest[1], digest[2], digest[3], digest[4],
|
||||
digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
|
||||
digest[11], digest[12], digest[13], digest[14], digest[15]);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
Curl_safefree(response);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -470,6 +478,40 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
}
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_xoauth2_message()
|
||||
*
|
||||
* This is used to generate an already encoded XOAUTH2 message ready
|
||||
* for sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* user [in] - The user name.
|
||||
* bearer [in] - The XOAUTH Bearer token.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
||||
const char *user,
|
||||
const char *bearer,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
char *xoauth;
|
||||
|
||||
xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
|
||||
|
||||
if(!xoauth)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, xoauth, strlen(xoauth), outptr,
|
||||
outlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_cleanup()
|
||||
*
|
||||
|
@@ -24,6 +24,10 @@
|
||||
|
||||
#include "pingpong.h"
|
||||
|
||||
/* Authentication mechanism values */
|
||||
#define SASL_AUTH_NONE 0
|
||||
#define SASL_AUTH_ANY ~0U
|
||||
|
||||
/* Authentication mechanism flags */
|
||||
#define SASL_MECH_LOGIN (1 << 0)
|
||||
#define SASL_MECH_PLAIN (1 << 1)
|
||||
@@ -32,10 +36,22 @@
|
||||
#define SASL_MECH_GSSAPI (1 << 4)
|
||||
#define SASL_MECH_EXTERNAL (1 << 5)
|
||||
#define SASL_MECH_NTLM (1 << 6)
|
||||
#define SASL_MECH_XOAUTH2 (1 << 7)
|
||||
|
||||
/* Authentication mechanism values */
|
||||
#define SASL_AUTH_NONE 0
|
||||
#define SASL_AUTH_ANY ~0
|
||||
/* Authentication mechanism strings */
|
||||
#define SASL_MECH_STRING_LOGIN "LOGIN"
|
||||
#define SASL_MECH_STRING_PLAIN "PLAIN"
|
||||
#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
|
||||
#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
|
||||
#define SASL_MECH_STRING_GSSAPI "GSSAPI"
|
||||
#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
|
||||
#define SASL_MECH_STRING_NTLM "NTLM"
|
||||
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
|
||||
|
||||
/* This is used to test whether the line starts with the given mechanism */
|
||||
#define sasl_mech_equal(line, wordlen, mech) \
|
||||
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
|
||||
!memcmp(line, mech, wordlen))
|
||||
|
||||
/* This is used to generate a base64 encoded PLAIN authentication message */
|
||||
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||
@@ -85,6 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
/* This is used to generate a base64 encoded XOAUTH2 authentication message
|
||||
containing the user name and bearer token */
|
||||
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
||||
const char *user,
|
||||
const char *bearer,
|
||||
char **outptr, size_t *outlen);
|
||||
|
||||
/* This is used to cleanup any libraries or curl modules used by the sasl
|
||||
functions */
|
||||
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#ifndef HEADER_CURL_KRB4_H
|
||||
#define HEADER_CURL_KRB4_H
|
||||
#ifndef HEADER_CURL_SECURITY_H
|
||||
#define HEADER_CURL_SECURITY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@@ -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
|
||||
@@ -34,24 +34,18 @@ struct Curl_sec_client_mech {
|
||||
int (*decode)(void *, void*, int, int, struct connectdata *);
|
||||
};
|
||||
|
||||
|
||||
#define AUTH_OK 0
|
||||
#define AUTH_CONTINUE 1
|
||||
#define AUTH_ERROR 2
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
|
||||
#endif
|
||||
#ifdef HAVE_GSSAPI
|
||||
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
|
||||
#endif
|
||||
|
||||
CURLcode Curl_krb_kauth(struct connectdata *conn);
|
||||
int Curl_sec_read_msg (struct connectdata *conn, char *,
|
||||
enum protection_level);
|
||||
void Curl_sec_end (struct connectdata *);
|
||||
CURLcode Curl_sec_login (struct connectdata *);
|
||||
int Curl_sec_request_prot (struct connectdata *conn, const char *level);
|
||||
|
||||
#endif /* HEADER_CURL_KRB4_H */
|
||||
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_SECURITY_H */
|
@@ -440,7 +440,7 @@ typedef int sig_atomic_t;
|
||||
* (or equivalent) on this platform to hide platform details to code using it.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) && !defined(USE_LWIPSOCK)
|
||||
#define ERRNO ((int)GetLastError())
|
||||
#define SET_ERRNO(x) (SetLastError((DWORD)(x)))
|
||||
#else
|
||||
|
438
lib/easy.c
438
lib/easy.c
@@ -453,70 +453,275 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_easy_perform() is the external interface that performs a blocking
|
||||
* transfer as previously setup.
|
||||
#ifdef CURLDEBUG
|
||||
|
||||
struct socketmonitor {
|
||||
struct socketmonitor *next; /* the next node in the list or NULL */
|
||||
struct pollfd socket; /* socket info of what to monitor */
|
||||
};
|
||||
|
||||
struct events {
|
||||
long ms; /* timeout, run the timeout function when reached */
|
||||
bool msbump; /* set TRUE when timeout is set by callback */
|
||||
int num_sockets; /* number of nodes in the monitor list */
|
||||
struct socketmonitor *list; /* list of sockets to monitor */
|
||||
int running_handles; /* store the returned number */
|
||||
};
|
||||
|
||||
/* events_timer
|
||||
*
|
||||
* CONCEPT: This function creates a multi handle, adds the easy handle to it,
|
||||
* runs curl_multi_perform() until the transfer is done, then detaches the
|
||||
* easy handle, destroys the multi handle and returns the easy handle's return
|
||||
* code.
|
||||
*
|
||||
* REALITY: it can't just create and destroy the multi handle that easily. It
|
||||
* needs to keep it around since if this easy handle is used again by this
|
||||
* function, the same multi handle must be re-used so that the same pools and
|
||||
* caches can be used.
|
||||
* Callback that gets called with a new value when the timeout should be
|
||||
* updated.
|
||||
*/
|
||||
CURLcode curl_easy_perform(CURL *easy)
|
||||
|
||||
static int events_timer(CURLM *multi, /* multi handle */
|
||||
long timeout_ms, /* see above */
|
||||
void *userp) /* private callback pointer */
|
||||
{
|
||||
struct events *ev = userp;
|
||||
(void)multi;
|
||||
if(timeout_ms == -1)
|
||||
/* timeout removed */
|
||||
timeout_ms = 0;
|
||||
else if(timeout_ms == 0)
|
||||
/* timeout is already reached! */
|
||||
timeout_ms = 1; /* trigger asap */
|
||||
|
||||
ev->ms = timeout_ms;
|
||||
ev->msbump = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* poll2cselect
|
||||
*
|
||||
* convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
|
||||
*/
|
||||
static int poll2cselect(int pollmask)
|
||||
{
|
||||
int omask=0;
|
||||
if(pollmask & POLLIN)
|
||||
omask |= CURL_CSELECT_IN;
|
||||
if(pollmask & POLLOUT)
|
||||
omask |= CURL_CSELECT_OUT;
|
||||
if(pollmask & POLLERR)
|
||||
omask |= CURL_CSELECT_ERR;
|
||||
return omask;
|
||||
}
|
||||
|
||||
|
||||
/* socketcb2poll
|
||||
*
|
||||
* convert from libcurl' CURL_POLL_* bit definitions to poll()'s
|
||||
*/
|
||||
static short socketcb2poll(int pollmask)
|
||||
{
|
||||
short omask=0;
|
||||
if(pollmask & CURL_POLL_IN)
|
||||
omask |= POLLIN;
|
||||
if(pollmask & CURL_POLL_OUT)
|
||||
omask |= POLLOUT;
|
||||
return omask;
|
||||
}
|
||||
|
||||
/* events_socket
|
||||
*
|
||||
* Callback that gets called with information about socket activity to
|
||||
* monitor.
|
||||
*/
|
||||
static int events_socket(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp, /* private callback
|
||||
pointer */
|
||||
void *socketp) /* private socket
|
||||
pointer */
|
||||
{
|
||||
struct events *ev = userp;
|
||||
struct socketmonitor *m;
|
||||
struct socketmonitor *prev=NULL;
|
||||
(void)socketp;
|
||||
|
||||
m = ev->list;
|
||||
while(m) {
|
||||
if(m->socket.fd == s) {
|
||||
|
||||
if(what == CURL_POLL_REMOVE) {
|
||||
struct socketmonitor *nxt = m->next;
|
||||
/* remove this node from the list of monitored sockets */
|
||||
if(prev)
|
||||
prev->next = nxt;
|
||||
else
|
||||
ev->list = nxt;
|
||||
free(m);
|
||||
m = nxt;
|
||||
infof(easy, "socket cb: socket %d REMOVED\n", s);
|
||||
}
|
||||
else {
|
||||
/* The socket 's' is already being monitored, update the activity
|
||||
mask. Convert from libcurl bitmask to the poll one. */
|
||||
m->socket.events = socketcb2poll(what);
|
||||
infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
|
||||
what&CURL_POLL_IN?"IN":"",
|
||||
what&CURL_POLL_OUT?"OUT":"");
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = m;
|
||||
m = m->next; /* move to next node */
|
||||
}
|
||||
if(!m) {
|
||||
if(what == CURL_POLL_REMOVE) {
|
||||
/* this happens a bit too often, libcurl fix perhaps? */
|
||||
/* fprintf(stderr,
|
||||
"%s: socket %d asked to be REMOVED but not present!\n",
|
||||
__func__, s); */
|
||||
}
|
||||
else {
|
||||
m = malloc(sizeof(struct socketmonitor));
|
||||
m->next = ev->list;
|
||||
m->socket.fd = s;
|
||||
m->socket.events = socketcb2poll(what);
|
||||
m->socket.revents = 0;
|
||||
ev->list = m;
|
||||
infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
|
||||
what&CURL_POLL_IN?"IN":"",
|
||||
what&CURL_POLL_OUT?"OUT":"");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* events_setup()
|
||||
*
|
||||
* Do the multi handle setups that only event-based transfers need.
|
||||
*/
|
||||
static void events_setup(CURLM *multi, struct events *ev)
|
||||
{
|
||||
/* timer callback */
|
||||
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
|
||||
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
|
||||
|
||||
/* socket callback */
|
||||
curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
|
||||
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
|
||||
}
|
||||
|
||||
|
||||
/* wait_or_timeout()
|
||||
*
|
||||
* waits for activity on any of the given sockets, or the timeout to trigger.
|
||||
*/
|
||||
|
||||
static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
{
|
||||
CURLM *multi;
|
||||
CURLMcode mcode;
|
||||
CURLcode code = CURLE_OK;
|
||||
CURLMsg *msg;
|
||||
bool done = FALSE;
|
||||
int rc;
|
||||
struct SessionHandle *data = easy;
|
||||
CURLMcode mcode;
|
||||
CURLcode rc = CURLE_OK;
|
||||
|
||||
while(!done) {
|
||||
CURLMsg *msg;
|
||||
struct socketmonitor *m;
|
||||
struct pollfd *f;
|
||||
struct pollfd fds[4];
|
||||
int numfds=0;
|
||||
int pollrc;
|
||||
int i;
|
||||
struct timeval before;
|
||||
struct timeval after;
|
||||
|
||||
/* populate the fds[] array */
|
||||
for(m = ev->list, f=&fds[0]; m; m = m->next) {
|
||||
f->fd = m->socket.fd;
|
||||
f->events = m->socket.events;
|
||||
f->revents = 0;
|
||||
/* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
|
||||
f++;
|
||||
numfds++;
|
||||
}
|
||||
|
||||
/* get the time stamp to use to figure out how long poll takes */
|
||||
before = curlx_tvnow();
|
||||
|
||||
/* wait for activity or timeout */
|
||||
pollrc = Curl_poll(fds, numfds, (int)ev->ms);
|
||||
|
||||
after = curlx_tvnow();
|
||||
|
||||
ev->msbump = FALSE; /* reset here */
|
||||
|
||||
if(0 == pollrc) {
|
||||
/* timeout! */
|
||||
ev->ms = 0;
|
||||
/* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
|
||||
mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
|
||||
&ev->running_handles);
|
||||
}
|
||||
else if(pollrc > 0) {
|
||||
/* loop over the monitored sockets to see which ones had activity */
|
||||
for(i = 0; i< numfds; i++) {
|
||||
if(fds[i].revents) {
|
||||
/* socket activity, tell libcurl */
|
||||
int act = poll2cselect(fds[i].revents); /* convert */
|
||||
infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
|
||||
fds[i].fd);
|
||||
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
|
||||
&ev->running_handles);
|
||||
}
|
||||
}
|
||||
|
||||
if(!ev->msbump)
|
||||
/* If nothing updated the timeout, we decrease it by the spent time.
|
||||
* If it was updated, it has the new timeout time stored already.
|
||||
*/
|
||||
ev->ms += curlx_tvdiff(after, before);
|
||||
|
||||
}
|
||||
if(mcode)
|
||||
return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
|
||||
|
||||
/* we don't really care about the "msgs_in_queue" value returned in the
|
||||
second argument */
|
||||
msg = curl_multi_info_read(multi, &pollrc);
|
||||
if(msg) {
|
||||
rc = msg->data.result;
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* easy_events()
|
||||
*
|
||||
* Runs a transfer in a blocking manner using the events-based API
|
||||
*/
|
||||
static CURLcode easy_events(CURLM *multi)
|
||||
{
|
||||
struct events evs= {2, FALSE, 0, NULL, 0};
|
||||
|
||||
/* if running event-based, do some further multi inits */
|
||||
events_setup(multi, &evs);
|
||||
|
||||
return wait_or_timeout(multi, &evs);
|
||||
}
|
||||
#else /* CURLDEBUG */
|
||||
/* when not built with debug, this function doesn't exist */
|
||||
#define easy_events(x) CURLE_NOT_BUILT_IN
|
||||
#endif
|
||||
|
||||
static CURLcode easy_transfer(CURLM *multi)
|
||||
{
|
||||
bool done = FALSE;
|
||||
CURLMcode mcode = CURLM_OK;
|
||||
CURLcode code = CURLE_OK;
|
||||
struct timeval before;
|
||||
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;
|
||||
|
||||
if(data->multi) {
|
||||
failf(data, "easy handled already used in multi handle");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
if(data->multi_easy)
|
||||
multi = data->multi_easy;
|
||||
else {
|
||||
/* this multi handle will only ever have a single easy handled attached
|
||||
to it, so make it use minimal hashes */
|
||||
multi = Curl_multi_handle(1, 3);
|
||||
if(!multi)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->multi_easy = multi;
|
||||
}
|
||||
|
||||
/* Copy the MAXCONNECTS option to the multi handle */
|
||||
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
|
||||
|
||||
mcode = curl_multi_add_handle(multi, easy);
|
||||
if(mcode) {
|
||||
curl_multi_cleanup(multi);
|
||||
if(mcode == CURLM_OUT_OF_MEMORY)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
else
|
||||
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;
|
||||
|
||||
while(!done && !mcode) {
|
||||
int still_running;
|
||||
@@ -556,17 +761,85 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
|
||||
/* only read 'still_running' if curl_multi_perform() return OK */
|
||||
if((mcode == CURLM_OK) && !still_running) {
|
||||
msg = curl_multi_info_read(multi, &rc);
|
||||
int rc;
|
||||
CURLMsg *msg = curl_multi_info_read(multi, &rc);
|
||||
if(msg) {
|
||||
code = msg->data.result;
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* easy_perform() is the external interface that performs a blocking
|
||||
* transfer as previously setup.
|
||||
*
|
||||
* CONCEPT: This function creates a multi handle, adds the easy handle to it,
|
||||
* runs curl_multi_perform() until the transfer is done, then detaches the
|
||||
* easy handle, destroys the multi handle and returns the easy handle's return
|
||||
* code.
|
||||
*
|
||||
* REALITY: it can't just create and destroy the multi handle that easily. It
|
||||
* needs to keep it around since if this easy handle is used again by this
|
||||
* function, the same multi handle must be re-used so that the same pools and
|
||||
* caches can be used.
|
||||
*
|
||||
* DEBUG: if 'events' is set TRUE, this function will use a replacement engine
|
||||
* instead of curl_multi_perform() and use curl_multi_socket_action().
|
||||
*/
|
||||
static CURLcode easy_perform(struct SessionHandle *data, bool events)
|
||||
{
|
||||
CURLM *multi;
|
||||
CURLMcode mcode;
|
||||
CURLcode code = CURLE_OK;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
if(data->multi) {
|
||||
failf(data, "easy handled already used in multi handle");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
if(data->multi_easy)
|
||||
multi = data->multi_easy;
|
||||
else {
|
||||
/* this multi handle will only ever have a single easy handled attached
|
||||
to it, so make it use minimal hashes */
|
||||
multi = Curl_multi_handle(1, 3);
|
||||
if(!multi)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->multi_easy = multi;
|
||||
}
|
||||
|
||||
/* Copy the MAXCONNECTS option to the multi handle */
|
||||
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
|
||||
|
||||
mcode = curl_multi_add_handle(multi, data);
|
||||
if(mcode) {
|
||||
curl_multi_cleanup(multi);
|
||||
if(mcode == CURLM_OUT_OF_MEMORY)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
else
|
||||
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;
|
||||
|
||||
/* run the transfer */
|
||||
code = events ? easy_events(multi) : easy_transfer(multi);
|
||||
|
||||
/* ignoring the return code isn't nice, but atm we can't really handle
|
||||
a failure here, room for future improvement! */
|
||||
(void)curl_multi_remove_handle(multi, easy);
|
||||
(void)curl_multi_remove_handle(multi, data);
|
||||
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
@@ -574,6 +847,28 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* curl_easy_perform() is the external interface that performs a blocking
|
||||
* transfer as previously setup.
|
||||
*/
|
||||
CURLcode curl_easy_perform(CURL *easy)
|
||||
{
|
||||
return easy_perform(easy, FALSE);
|
||||
}
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/*
|
||||
* curl_easy_perform_ev() is the external interface that performs a blocking
|
||||
* transfer using the event-based API internally.
|
||||
*/
|
||||
CURLcode curl_easy_perform_ev(CURL *easy)
|
||||
{
|
||||
return easy_perform(easy, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
|
||||
* easy handle.
|
||||
@@ -591,22 +886,6 @@ void curl_easy_cleanup(CURL *curl)
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a pointed to the multi handle within the easy handle's data struct.
|
||||
*/
|
||||
void Curl_easy_addmulti(struct SessionHandle *data,
|
||||
void *multi)
|
||||
{
|
||||
data->multi = multi;
|
||||
}
|
||||
|
||||
void Curl_easy_initHandleData(struct SessionHandle *data)
|
||||
{
|
||||
memset(&data->req, 0, sizeof(struct SingleRequest));
|
||||
|
||||
data->req.maxdownload = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_easy_getinfo() is an external interface that allows an app to retrieve
|
||||
* information from a performed transfer and similar.
|
||||
@@ -703,8 +982,6 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
|
||||
Curl_convert_setup(outcurl);
|
||||
|
||||
Curl_easy_initHandleData(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
/* we reach this point and thus we are OK */
|
||||
@@ -738,7 +1015,7 @@ void curl_easy_reset(CURL *curl)
|
||||
|
||||
data->state.path = NULL;
|
||||
|
||||
Curl_safefree(data->state.proto.generic);
|
||||
Curl_free_request_state(data);
|
||||
|
||||
/* zero out UserDefined data: */
|
||||
Curl_freeset(data);
|
||||
@@ -748,9 +1025,6 @@ void curl_easy_reset(CURL *curl)
|
||||
/* zero out Progress data: */
|
||||
memset(&data->progress, 0, sizeof(struct Progress));
|
||||
|
||||
/* init Handle data */
|
||||
Curl_easy_initHandleData(data);
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
}
|
||||
|
@@ -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
|
||||
@@ -25,9 +25,9 @@
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by easy.c
|
||||
*/
|
||||
void Curl_easy_addmulti(struct SessionHandle *data, void *multi);
|
||||
|
||||
void Curl_easy_initHandleData(struct SessionHandle *data);
|
||||
#ifdef CURLDEBUG
|
||||
CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_EASYIF_H */
|
||||
|
||||
|
51
lib/file.c
51
lib/file.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
|
||||
@@ -90,7 +90,7 @@ static CURLcode file_done(struct connectdata *conn,
|
||||
static CURLcode file_connect(struct connectdata *conn, bool *done);
|
||||
static CURLcode file_disconnect(struct connectdata *conn,
|
||||
bool dead_connection);
|
||||
|
||||
static CURLcode file_setup_connection(struct connectdata *conn);
|
||||
|
||||
/*
|
||||
* FILE scheme handler.
|
||||
@@ -98,7 +98,7 @@ static CURLcode file_disconnect(struct connectdata *conn,
|
||||
|
||||
const struct Curl_handler Curl_handler_file = {
|
||||
"FILE", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
file_setup_connection, /* setup_connection */
|
||||
file_do, /* do_it */
|
||||
file_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -117,6 +117,16 @@ const struct Curl_handler Curl_handler_file = {
|
||||
};
|
||||
|
||||
|
||||
static CURLcode file_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
/* allocate the FILE specific struct */
|
||||
conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
|
||||
if(!conn->data->req.protop)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if this is a range download, and if so, set the internal variables
|
||||
properly. This code is copied from the FTP implementation and might as
|
||||
@@ -179,39 +189,17 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *real_path;
|
||||
struct FILEPROTO *file;
|
||||
struct FILEPROTO *file = data->req.protop;
|
||||
int fd;
|
||||
#ifdef DOS_FILESYSTEM
|
||||
int i;
|
||||
char *actual_path;
|
||||
#endif
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
|
||||
if(!real_path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(!data->state.proto.file) {
|
||||
file = calloc(1, sizeof(struct FILEPROTO));
|
||||
if(!file) {
|
||||
free(real_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
data->state.proto.file = file;
|
||||
}
|
||||
else {
|
||||
/* file is not a protocol that can deal with "persistancy" */
|
||||
file = data->state.proto.file;
|
||||
Curl_safefree(file->freepath);
|
||||
file->path = NULL;
|
||||
if(file->fd != -1)
|
||||
close(file->fd);
|
||||
file->fd = -1;
|
||||
}
|
||||
|
||||
#ifdef DOS_FILESYSTEM
|
||||
/* If the first character is a slash, and there's
|
||||
something that looks like a drive at the beginning of
|
||||
@@ -262,7 +250,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
|
||||
static CURLcode file_done(struct connectdata *conn,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->state.proto.file;
|
||||
struct FILEPROTO *file = conn->data->req.protop;
|
||||
(void)status; /* not used */
|
||||
(void)premature; /* not used */
|
||||
|
||||
@@ -280,7 +268,7 @@ static CURLcode file_done(struct connectdata *conn,
|
||||
static CURLcode file_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->state.proto.file;
|
||||
struct FILEPROTO *file = conn->data->req.protop;
|
||||
(void)dead_connection; /* not used */
|
||||
|
||||
if(file) {
|
||||
@@ -302,7 +290,7 @@ static CURLcode file_disconnect(struct connectdata *conn,
|
||||
|
||||
static CURLcode file_upload(struct connectdata *conn)
|
||||
{
|
||||
struct FILEPROTO *file = conn->data->state.proto.file;
|
||||
struct FILEPROTO *file = conn->data->req.protop;
|
||||
const char *dir = strchr(file->path, DIRSEP);
|
||||
int fd;
|
||||
int mode;
|
||||
@@ -440,6 +428,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
curl_off_t bytecount = 0;
|
||||
int fd;
|
||||
struct timeval now = Curl_tvnow();
|
||||
struct FILEPROTO *file;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
|
||||
@@ -449,8 +438,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
if(data->set.upload)
|
||||
return file_upload(conn);
|
||||
|
||||
file = conn->data->req.protop;
|
||||
|
||||
/* get the fd from the connection phase */
|
||||
fd = conn->data->state.proto.file->fd;
|
||||
fd = file->fd;
|
||||
|
||||
/* VMS: This only works reliable for STREAMLF files */
|
||||
if(-1 != fstat(fd, &statbuf)) {
|
||||
|
237
lib/ftp.c
237
lib/ftp.c
@@ -59,11 +59,7 @@
|
||||
#include "ftp.h"
|
||||
#include "fileinfo.h"
|
||||
#include "ftplistparser.h"
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#include "krb4.h"
|
||||
#endif
|
||||
|
||||
#include "curl_sec.h"
|
||||
#include "strtoofft.h"
|
||||
#include "strequal.h"
|
||||
#include "sslgen.h"
|
||||
@@ -225,7 +221,7 @@ const struct Curl_handler Curl_handler_ftps = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_ftp_proxy = {
|
||||
"FTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -251,7 +247,7 @@ static const struct Curl_handler Curl_handler_ftp_proxy = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_ftps_proxy = {
|
||||
"FTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -493,7 +489,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
|
||||
static CURLcode InitiateTransfer(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn->ssl[SECONDARYSOCKET].use) {
|
||||
@@ -615,7 +611,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
{
|
||||
struct connectdata *conn = pp->conn;
|
||||
struct SessionHandle *data = conn->data;
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
char * const buf = data->state.buffer;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -623,7 +619,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
|
||||
result = Curl_pp_readresp(sockfd, pp, &code, size);
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#if defined(HAVE_GSSAPI)
|
||||
/* handle the security-oriented responses 6xx ***/
|
||||
/* FIXME: some errorchecking perhaps... ***/
|
||||
switch(code) {
|
||||
@@ -775,17 +771,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This is the ONLY way to change FTP state! */
|
||||
static void _state(struct connectdata *conn,
|
||||
ftpstate newstate
|
||||
#ifdef DEBUGBUILD
|
||||
, int lineno
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
/* for debug purposes */
|
||||
static const char * const names[]={
|
||||
static const char * const ftp_state_names[]={
|
||||
"STOP",
|
||||
"WAIT220",
|
||||
"AUTH",
|
||||
@@ -823,11 +811,21 @@ static void _state(struct connectdata *conn,
|
||||
"QUIT"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* This is the ONLY way to change FTP state! */
|
||||
static void _state(struct connectdata *conn,
|
||||
ftpstate newstate
|
||||
#ifdef DEBUGBUILD
|
||||
, int lineno
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
#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",
|
||||
(void *)ftpc, lineno, names[ftpc->state], names[newstate]);
|
||||
(void *)ftpc, lineno, ftp_state_names[ftpc->state],
|
||||
ftp_state_names[newstate]);
|
||||
#endif
|
||||
ftpc->state = newstate;
|
||||
}
|
||||
@@ -835,7 +833,7 @@ static void _state(struct connectdata *conn,
|
||||
static CURLcode ftp_state_user(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
/* send USER */
|
||||
PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
|
||||
|
||||
@@ -874,33 +872,23 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
/* When in DO_MORE state, we could be either waiting for us to connect to a
|
||||
remote site, or we could wait for that site to connect to us. Or just
|
||||
handle ordinary commands.
|
||||
|
||||
When waiting for a connect, we can be in FTP_STOP state (or we're in
|
||||
FTP_STOR when we do an upload) and then we wait for the secondary socket
|
||||
to become writeable. . If we're in another state, we're still handling
|
||||
commands on the control (primary) connection.
|
||||
|
||||
* remote site, or we could wait for that site to connect to us. Or just
|
||||
* handle ordinary commands.
|
||||
*/
|
||||
|
||||
switch(ftpc->state) {
|
||||
case FTP_STOP:
|
||||
case FTP_STOR:
|
||||
break;
|
||||
default:
|
||||
if(FTP_STOP == ftpc->state) {
|
||||
/* if stopped and still in this state, then we're also waiting for a
|
||||
connect on the secondary connection */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
socks[1] = conn->sock[SECONDARYSOCKET];
|
||||
|
||||
return GETSOCK_READSOCK(FIRSTSOCKET) |
|
||||
GETSOCK_WRITESOCK(SECONDARYSOCKET);
|
||||
}
|
||||
else
|
||||
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
|
||||
}
|
||||
|
||||
socks[0] = conn->sock[SECONDARYSOCKET];
|
||||
if(ftpc->wait_data_conn) {
|
||||
socks[1] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_READSOCK(0) | GETSOCK_READSOCK(1);
|
||||
}
|
||||
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
/* This is called after the FTP_QUOTE state is passed.
|
||||
|
||||
ftp_state_cwd() sends the range of CWD commands to the server to change to
|
||||
@@ -1382,7 +1370,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
|
||||
static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
if(ftp->transfer != FTPTRANSFER_BODY) {
|
||||
@@ -1425,7 +1413,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
|
||||
static CURLcode ftp_state_rest(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
|
||||
@@ -1446,7 +1434,7 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
|
||||
static CURLcode ftp_state_size(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
|
||||
@@ -1557,7 +1545,7 @@ static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
|
||||
static CURLcode ftp_state_type(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
@@ -1614,7 +1602,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
||||
bool sizechecked)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
int seekerr = CURL_SEEKFUNC_OK;
|
||||
@@ -1712,7 +1700,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
bool quote=FALSE;
|
||||
struct curl_slist *item;
|
||||
@@ -2058,13 +2046,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
* FTP pointer
|
||||
*/
|
||||
struct HTTP http_proxy;
|
||||
struct FTP *ftp_save = data->state.proto.ftp;
|
||||
struct FTP *ftp_save = data->req.protop;
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
data->state.proto.http = &http_proxy;
|
||||
data->req.protop = &http_proxy;
|
||||
|
||||
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
|
||||
|
||||
data->state.proto.ftp = ftp_save;
|
||||
data->req.protop = ftp_save;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2124,7 +2112,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data=conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
switch(ftpcode) {
|
||||
@@ -2258,7 +2246,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data=conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
|
||||
@@ -2427,6 +2415,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
|
||||
if(data->set.ftp_use_port) {
|
||||
bool connected;
|
||||
|
||||
state(conn, FTP_STOP); /* no longer in STOR state */
|
||||
|
||||
result = AllowServerConnect(conn, &connected);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2450,7 +2440,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
char *buf = data->state.buffer;
|
||||
|
||||
if((ftpcode == 150) || (ftpcode == 125)) {
|
||||
@@ -2574,19 +2564,6 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
if(conn->data->set.krb) {
|
||||
/* We may need to issue a KAUTH here to have access to the files
|
||||
* do it if user supplied a password
|
||||
*/
|
||||
if(conn->passwd && *conn->passwd) {
|
||||
/* BLOCKING */
|
||||
result = Curl_krb_kauth(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(conn->ssl[FIRSTSOCKET].use) {
|
||||
/* PBSZ = PROTECTION BUFFER SIZE.
|
||||
|
||||
@@ -2618,7 +2595,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -2716,7 +2693,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
}
|
||||
|
||||
/* We have received a 220 response fine, now we proceed. */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
if(data->set.krb) {
|
||||
/* If not anonymous login, try a secure login. Note that this
|
||||
procedure is still BLOCKING. */
|
||||
@@ -3158,56 +3135,6 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize the struct FTP for the current SessionHandle. If
|
||||
* need be.
|
||||
*/
|
||||
|
||||
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
|
||||
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
|
||||
/* workaround icc 9.1 optimizer issue */
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
|
||||
static CURLcode ftp_init(struct connectdata *conn)
|
||||
{
|
||||
struct FTP *ftp;
|
||||
|
||||
if(NULL == conn->data->state.proto.ftp) {
|
||||
conn->data->state.proto.ftp = malloc(sizeof(struct FTP));
|
||||
if(NULL == conn->data->state.proto.ftp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ftp = conn->data->state.proto.ftp;
|
||||
|
||||
/* get some initial data into the ftp struct */
|
||||
ftp->bytecountp = &conn->data->req.bytecount;
|
||||
ftp->transfer = FTPTRANSFER_BODY;
|
||||
ftp->downloadsize = 0;
|
||||
|
||||
/* No need to duplicate user+password, the connectdata struct won't change
|
||||
during a session, but we re-init them here since on subsequent inits
|
||||
since the conn struct may have changed or been replaced.
|
||||
*/
|
||||
ftp->user = conn->user;
|
||||
ftp->passwd = conn->passwd;
|
||||
if(isBadFtpString(ftp->user))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
if(isBadFtpString(ftp->passwd))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
|
||||
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
|
||||
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
|
||||
/* workaround icc 9.1 optimizer issue */
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ftp_connect() should do everything that is to be considered a part of
|
||||
* the connection phase.
|
||||
@@ -3225,14 +3152,6 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
||||
|
||||
*done = FALSE; /* default to not done yet */
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
result = ftp_init(conn);
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
|
||||
/* We always support persistent connections on ftp */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
@@ -3272,7 +3191,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct pingpong *pp = &ftpc->pp;
|
||||
ssize_t nread;
|
||||
@@ -3689,7 +3608,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
bool complete = FALSE;
|
||||
|
||||
/* the ftp struct is inited in ftp_connect() */
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
|
||||
/* if the second connection isn't done yet, wait for it */
|
||||
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
||||
@@ -3837,7 +3756,7 @@ CURLcode ftp_perform(struct connectdata *conn,
|
||||
|
||||
if(conn->data->set.opt_no_body) {
|
||||
/* requested no body means no transfer... */
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
ftp->transfer = FTPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
@@ -4099,17 +4018,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
|
||||
*done = FALSE; /* default to false */
|
||||
ftpc->wait_data_conn = FALSE; /* default to no such wait */
|
||||
|
||||
/*
|
||||
Since connections can be re-used between SessionHandles, this might be a
|
||||
connection already existing but on a fresh SessionHandle struct so we must
|
||||
make sure we have a good 'struct FTP' to play with. For new connections,
|
||||
the struct FTP is allocated and setup in the ftp_connect() function.
|
||||
*/
|
||||
Curl_reset_reqproto(conn);
|
||||
retcode = ftp_init(conn);
|
||||
if(retcode)
|
||||
return retcode;
|
||||
|
||||
if(conn->data->set.wildcardmatch) {
|
||||
retcode = wc_statemach(conn);
|
||||
if(conn->data->wildcard.state == CURLWC_SKIP ||
|
||||
@@ -4141,7 +4049,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
size_t write_len;
|
||||
char *sptr=s;
|
||||
CURLcode res = CURLE_OK;
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
enum protection_level data_sec = conn->data_prot;
|
||||
#endif
|
||||
|
||||
@@ -4161,12 +4069,12 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
return(res);
|
||||
|
||||
for(;;) {
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
&bytes_written);
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
|
||||
conn->data_prot = data_sec;
|
||||
#endif
|
||||
@@ -4268,7 +4176,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
|
||||
Curl_pp_disconnect(pp);
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
Curl_sec_end(conn);
|
||||
#endif
|
||||
|
||||
@@ -4287,7 +4195,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
/* the ftp struct is already inited in ftp_connect() */
|
||||
struct FTP *ftp = data->state.proto.ftp;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
const char *slash_pos; /* position of the first '/' char in curpos */
|
||||
const char *path_to_use = data->state.path;
|
||||
@@ -4342,7 +4250,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
dirlen++;
|
||||
|
||||
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
|
||||
slash_pos ? curlx_sztosi(dirlen) : 1,
|
||||
slash_pos ? curlx_uztosi(dirlen) : 1,
|
||||
NULL);
|
||||
if(!ftpc->dirs[0]) {
|
||||
freedirs(ftpc);
|
||||
@@ -4477,7 +4385,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
static CURLcode ftp_dophase_done(struct connectdata *conn,
|
||||
bool connected)
|
||||
{
|
||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if(connected) {
|
||||
@@ -4577,6 +4485,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *type;
|
||||
char command;
|
||||
struct FTP *ftp;
|
||||
|
||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel ftp operations through the proxy, we
|
||||
@@ -4592,18 +4501,18 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* We explicitly mark this connection as persistent here as we're doing
|
||||
* FTP over HTTP and thus we accidentally avoid setting this value
|
||||
* otherwise.
|
||||
*/
|
||||
conn->bits.close = FALSE;
|
||||
/* set it up as a HTTP connection instead */
|
||||
return conn->handler->setup_connection(conn);
|
||||
#else
|
||||
failf(data, "FTP over http proxy requires HTTP support built-in!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
|
||||
conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
|
||||
if(NULL == ftp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
data->state.path++; /* don't include the initial slash */
|
||||
data->state.slash_removed = TRUE; /* we've skipped the slash */
|
||||
|
||||
@@ -4636,6 +4545,24 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
|
||||
}
|
||||
}
|
||||
|
||||
/* get some initial data into the ftp struct */
|
||||
ftp->bytecountp = &conn->data->req.bytecount;
|
||||
ftp->transfer = FTPTRANSFER_BODY;
|
||||
ftp->downloadsize = 0;
|
||||
|
||||
/* No need to duplicate user+password, the connectdata struct won't change
|
||||
during a session, but we re-init them here since on subsequent inits
|
||||
since the conn struct may have changed or been replaced.
|
||||
*/
|
||||
ftp->user = conn->user;
|
||||
ftp->passwd = conn->passwd;
|
||||
if(isBadFtpString(ftp->user))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
if(isBadFtpString(ftp->passwd))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
|
||||
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
21
lib/hostip.h
21
lib/hostip.h
@@ -200,6 +200,27 @@ extern sigjmp_buf curl_jmpenv;
|
||||
*/
|
||||
CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* outgoing interface to use for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
|
||||
const char *interf);
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* local IPv4 address to use as source address for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
||||
const char *local_ip4);
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* local IPv6 address to use as source address for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
||||
const char *local_ip6);
|
||||
|
||||
/*
|
||||
* Clean off entries from the cache
|
||||
*/
|
||||
|
@@ -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,7 +140,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
|
||||
#if defined(HAVE_GETADDRINFO_THREADSAFE)
|
||||
else {
|
||||
struct addrinfo hints;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
@@ -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
|
||||
@@ -168,7 +168,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||
struct addrinfo hints;
|
||||
Curl_addrinfo *res;
|
||||
int error;
|
||||
char sbuf[NI_MAXSERV];
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
char addrbuf[128];
|
||||
int pf;
|
||||
|
@@ -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
|
||||
@@ -72,4 +72,40 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* outgoing interface to use for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
|
||||
const char *interf)
|
||||
{
|
||||
(void)data;
|
||||
(void)interf;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* local IPv4 address to use as source address for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
||||
const char *local_ip4)
|
||||
{
|
||||
(void)data;
|
||||
(void)local_ip4;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function provided by the resolver backend to set
|
||||
* local IPv6 address to use as source address for DNS requests
|
||||
*/
|
||||
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
|
||||
const char *local_ip6)
|
||||
{
|
||||
(void)data;
|
||||
(void)local_ip6;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
#endif /* truly sync */
|
||||
|
74
lib/http.c
74
lib/http.c
@@ -75,6 +75,7 @@
|
||||
#include "non-ascii.h"
|
||||
#include "bundles.h"
|
||||
#include "pipeline.h"
|
||||
#include "http2.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn,
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_http = {
|
||||
"HTTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = {
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_https = {
|
||||
"HTTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = {
|
||||
#endif
|
||||
|
||||
|
||||
CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
||||
{
|
||||
/* allocate the HTTP-specific struct for the SessionHandle, only to survive
|
||||
during this request */
|
||||
DEBUGASSERT(conn->data->req.protop == NULL);
|
||||
|
||||
conn->data->req.protop = calloc(1, sizeof(struct HTTP));
|
||||
if(!conn->data->req.protop)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* checkheaders() checks the linked list of custom HTTP headers for a
|
||||
* particular header (prefix).
|
||||
@@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick)
|
||||
static CURLcode http_perhapsrewind(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct HTTP *http = data->state.proto.http;
|
||||
struct HTTP *http = data->req.protop;
|
||||
curl_off_t bytessent;
|
||||
curl_off_t expectsend = -1; /* default is unknown */
|
||||
|
||||
@@ -948,7 +962,7 @@ static size_t readmoredata(char *buffer,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct HTTP *http = conn->data->state.proto.http;
|
||||
struct HTTP *http = conn->data->req.protop;
|
||||
size_t fullsize = size * nitems;
|
||||
|
||||
if(0 == http->postsize)
|
||||
@@ -1019,7 +1033,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
CURLcode res;
|
||||
char *ptr;
|
||||
size_t size;
|
||||
struct HTTP *http = conn->data->state.proto.http;
|
||||
struct HTTP *http = conn->data->req.protop;
|
||||
size_t sendsize;
|
||||
curl_socket_t sockfd;
|
||||
size_t headersize;
|
||||
@@ -1402,7 +1416,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct HTTP *http =data->state.proto.http;
|
||||
struct HTTP *http =data->req.protop;
|
||||
|
||||
Curl_unencode_cleanup(conn);
|
||||
|
||||
@@ -1442,6 +1456,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
if(!premature && /* this check is pointless when DONE is called before the
|
||||
entire operation is complete */
|
||||
!conn->bits.retry &&
|
||||
!data->set.connect_only &&
|
||||
((http->readbytecount +
|
||||
data->req.headerbytecount -
|
||||
data->req.deductheadercount)) <= 0) {
|
||||
@@ -1456,14 +1471,19 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
}
|
||||
|
||||
|
||||
/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it
|
||||
are if the user specifically requested HTTP 1.0, if the server we are
|
||||
connected to only supports 1.0, or if any server previously contacted to
|
||||
handle this request only supports 1.0. */
|
||||
static bool use_http_1_1(const struct SessionHandle *data,
|
||||
/*
|
||||
* Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
|
||||
* to avoid it include:
|
||||
*
|
||||
* - if the user specifically requested HTTP 1.0
|
||||
* - if the server we are connected to only supports 1.0
|
||||
* - if any server previously contacted to handle this request only supports
|
||||
* 1.0.
|
||||
*/
|
||||
static bool use_http_1_1plus(const struct SessionHandle *data,
|
||||
const struct connectdata *conn)
|
||||
{
|
||||
return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
|
||||
return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
|
||||
((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
|
||||
((conn->httpversion == 11) ||
|
||||
((conn->httpversion != 10) &&
|
||||
@@ -1479,7 +1499,7 @@ static CURLcode expect100(struct SessionHandle *data,
|
||||
const char *ptr;
|
||||
data->state.expect100header = FALSE; /* default to false unless it is set
|
||||
to TRUE below */
|
||||
if(use_http_1_1(data, conn)) {
|
||||
if(use_http_1_1plus(data, conn)) {
|
||||
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
|
||||
100-continue to the headers which actually speeds up post operations
|
||||
(as there is one packet coming back from the web server) */
|
||||
@@ -1655,20 +1675,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
the rest of the request in the PERFORM phase. */
|
||||
*done = TRUE;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
if(!data->state.proto.http) {
|
||||
/* Only allocate this struct if we don't already have it! */
|
||||
|
||||
http = calloc(1, sizeof(struct HTTP));
|
||||
if(!http)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->state.proto.http = http;
|
||||
}
|
||||
else
|
||||
http = data->state.proto.http;
|
||||
http = data->req.protop;
|
||||
|
||||
if(!data->state.this_is_a_follow) {
|
||||
/* this is not a followed location, get the original host name */
|
||||
@@ -1795,7 +1802,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(conn->bits.authneg)
|
||||
/* don't enable chunked during auth neg */
|
||||
;
|
||||
else if(use_http_1_1(data, conn)) {
|
||||
else if(use_http_1_1plus(data, conn)) {
|
||||
/* HTTP, upload, unknown file size and not HTTP 1.0 */
|
||||
data->req.upload_chunky = TRUE;
|
||||
}
|
||||
@@ -2095,7 +2102,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
/* Use 1.1 unless the user specifically asked for 1.0 or the server only
|
||||
supports 1.0 */
|
||||
httpstring= use_http_1_1(data, conn)?"1.1":"1.0";
|
||||
httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
|
||||
|
||||
/* initialize a dynamic send-buffer */
|
||||
req_buffer = Curl_add_buffer_init();
|
||||
@@ -2173,6 +2180,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(!(conn->handler->flags&PROTOPT_SSL) &&
|
||||
(data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
|
||||
/* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
|
||||
over SSL */
|
||||
result = Curl_http2_request(req_buffer, conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(CURL_DISABLE_COOKIES)
|
||||
if(data->cookies || addcookies) {
|
||||
struct Cookie *co=NULL; /* no cookies from start */
|
||||
|
17
lib/http.h
17
lib/http.h
@@ -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
|
||||
@@ -21,8 +21,14 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#endif
|
||||
|
||||
extern const struct Curl_handler Curl_handler_http;
|
||||
|
||||
#ifdef USE_SSL
|
||||
@@ -66,6 +72,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_setup_conn(struct connectdata *conn);
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
@@ -141,6 +148,14 @@ struct HTTP {
|
||||
points to an allocated send_buffer struct */
|
||||
};
|
||||
|
||||
struct http_conn {
|
||||
#ifdef USE_NGHTTP2
|
||||
nghttp2_session *h2;
|
||||
#else
|
||||
int unused; /* prevent a compiler warning */
|
||||
#endif
|
||||
};
|
||||
|
||||
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
struct connectdata *conn,
|
||||
ssize_t *nread,
|
||||
|
182
lib/http2.c
Normal file
182
lib/http2.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* 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_NGHTTP2
|
||||
#define _MPRINTF_REPLACE
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "urldata.h"
|
||||
#include "http2.h"
|
||||
#include "http.h"
|
||||
#include "sendf.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* include memdebug.h last */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Store nghttp2 version info in this buffer, Prefix with a space. Return
|
||||
* total length written.
|
||||
*/
|
||||
int Curl_http2_ver(char *p, size_t len)
|
||||
{
|
||||
nghttp2_info *h2 = nghttp2_version(0);
|
||||
return snprintf(p, len, " nghttp2/%s", h2->version_str);
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_send_callback type. Here we write |data| with
|
||||
* size |length| to the network and return the number of bytes actually
|
||||
* written. See the documentation of nghttp2_send_callback for the details.
|
||||
*/
|
||||
static ssize_t send_callback(nghttp2_session *h2,
|
||||
const uint8_t *data, size_t length, int flags,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
ssize_t written;
|
||||
CURLcode rc =
|
||||
Curl_write(conn, conn->sock[0], data, length, &written);
|
||||
(void)h2;
|
||||
(void)flags;
|
||||
|
||||
if(rc) {
|
||||
failf(conn->data, "Failed sending HTTP2 data");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
else if(!written)
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_recv_callback type. Here we read data from
|
||||
* the network and write them in |buf|. The capacity of |buf| is |length|
|
||||
* bytes. Returns the number of bytes stored in |buf|. See the documentation
|
||||
* of nghttp2_recv_callback for the details.
|
||||
*/
|
||||
static ssize_t recv_callback(nghttp2_session *h2,
|
||||
uint8_t *buf, size_t length, int flags,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
ssize_t nread;
|
||||
CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread);
|
||||
(void)h2;
|
||||
(void)flags;
|
||||
|
||||
if(rc) {
|
||||
failf(conn->data, "Failed recving HTTP2 data");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
if(!nread)
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is all callbacks nghttp2 calls
|
||||
*/
|
||||
static const nghttp2_session_callbacks callbacks = {
|
||||
send_callback,
|
||||
recv_callback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* The HTTP2 settings we send in the Upgrade request
|
||||
*/
|
||||
static nghttp2_settings_entry settings[] = {
|
||||
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
|
||||
{ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
|
||||
};
|
||||
|
||||
/*
|
||||
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
|
||||
*/
|
||||
CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
uint8_t binsettings[80];
|
||||
CURLcode result;
|
||||
ssize_t binlen;
|
||||
char *base64;
|
||||
size_t blen;
|
||||
|
||||
if(!conn->proto.httpc.h2) {
|
||||
/* The nghttp2 session is not yet setup, do it */
|
||||
int rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
|
||||
&callbacks, &conn);
|
||||
if(rc) {
|
||||
failf(conn->data, "Couldn't initialize nghttp2!");
|
||||
return CURLE_OUT_OF_MEMORY; /* most likely at least */
|
||||
}
|
||||
}
|
||||
|
||||
/* As long as we have a fixed set of settings, we don't have to dynamically
|
||||
* figure out the base64 strings since it'll always be the same. However,
|
||||
* the settings will likely not be fixed every time in the future.
|
||||
*/
|
||||
|
||||
/* this returns number of bytes it wrote */
|
||||
binlen = nghttp2_pack_settings_payload(binsettings,
|
||||
sizeof(binsettings),
|
||||
settings,
|
||||
sizeof(settings)/sizeof(settings[0]));
|
||||
if(!binlen) {
|
||||
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
|
||||
&base64, &blen);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_add_bufferf(req,
|
||||
"Connection: Upgrade, HTTP2-Settings\r\n"
|
||||
"Upgrade: %s\r\n"
|
||||
"HTTP2-Settings: %s\r\n",
|
||||
NGHTTP2_PROTO_VERSION_ID, base64);
|
||||
free(base64);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
42
lib/http2.h
Normal file
42
lib/http2.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef HEADER_CURL_HTTP2_H
|
||||
#define HEADER_CURL_HTTP2_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"
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
#include "http.h"
|
||||
/*
|
||||
* Store nghttp2 version info in this buffer, Prefix with a space. Return
|
||||
* total length written.
|
||||
*/
|
||||
int Curl_http2_ver(char *p, size_t len);
|
||||
|
||||
CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
struct connectdata *conn);
|
||||
#else /* USE_NGHTTP2 */
|
||||
#define Curl_http2_request(x,y) CURLE_OK
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_HTTP2_H */
|
||||
|
@@ -66,13 +66,13 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
* This function might be called several times in the multi interface case
|
||||
* if the proxy's CONNTECT response is not instant.
|
||||
*/
|
||||
prot_save = conn->data->state.proto.generic;
|
||||
prot_save = conn->data->req.protop;
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
conn->data->state.proto.http = &http_proxy;
|
||||
conn->data->req.protop = &http_proxy;
|
||||
conn->bits.close = FALSE;
|
||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
|
||||
conn->host.name, conn->remote_port);
|
||||
conn->data->state.proto.generic = prot_save;
|
||||
conn->data->req.protop = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
#else
|
||||
|
187
lib/imap.c
187
lib/imap.c
@@ -26,6 +26,7 @@
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC4959 IMAP Extension for SASL Initial Client Response
|
||||
* RFC5092 IMAP URL Scheme
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
@@ -163,7 +164,7 @@ const struct Curl_handler Curl_handler_imaps = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_imap_proxy = {
|
||||
"IMAP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -188,7 +189,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_imaps_proxy = {
|
||||
"IMAPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -268,7 +269,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
|
||||
static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
int *resp)
|
||||
{
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
const char *id = imapc->resptag;
|
||||
size_t id_len = strlen(id);
|
||||
@@ -307,7 +308,12 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
(strcmp(imap->custom, "STORE") ||
|
||||
!imap_matchresp(line, len, "FETCH")) &&
|
||||
strcmp(imap->custom, "SELECT") &&
|
||||
strcmp(imap->custom, "EXAMINE")))
|
||||
strcmp(imap->custom, "EXAMINE") &&
|
||||
strcmp(imap->custom, "SEARCH") &&
|
||||
strcmp(imap->custom, "EXPUNGE") &&
|
||||
strcmp(imap->custom, "LSUB") &&
|
||||
strcmp(imap->custom, "UID") &&
|
||||
strcmp(imap->custom, "NOOP")))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
@@ -330,7 +336,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Do we have a continuation response? */
|
||||
/* Do we have a continuation response? This should be a + symbol followed by
|
||||
a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
|
||||
APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
|
||||
some e-mail servers ignore this and only send a single + instead. */
|
||||
if((len == 3 && !memcmp("+", line, 1)) ||
|
||||
(len >= 2 && !memcmp("+ ", line, 2))) {
|
||||
switch(imapc->state) {
|
||||
@@ -343,6 +352,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
case IMAP_AUTHENTICATE_DIGESTMD5_RESP:
|
||||
case IMAP_AUTHENTICATE_NTLM:
|
||||
case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
|
||||
case IMAP_AUTHENTICATE_XOAUTH2:
|
||||
case IMAP_AUTHENTICATE_FINAL:
|
||||
case IMAP_APPEND:
|
||||
*resp = '+';
|
||||
@@ -385,6 +395,7 @@ static void state(struct connectdata *conn, imapstate newstate)
|
||||
"AUTHENTICATE_DIGESTMD5_RESP",
|
||||
"AUTHENTICATE_NTLM",
|
||||
"AUTHENTICATE_NTLM_TYPE2MSG",
|
||||
"AUTHENTICATE_XOAUTH2",
|
||||
"AUTHENTICATE_FINAL",
|
||||
"LOGIN",
|
||||
"LIST",
|
||||
@@ -547,13 +558,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||
mech = "DIGEST-MD5";
|
||||
mech = SASL_MECH_STRING_DIGEST_MD5;
|
||||
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
|
||||
imapc->authused = SASL_MECH_DIGEST_MD5;
|
||||
}
|
||||
else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||
(imapc->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||
mech = "CRAM-MD5";
|
||||
mech = SASL_MECH_STRING_CRAM_MD5;
|
||||
state1 = IMAP_AUTHENTICATE_CRAMMD5;
|
||||
imapc->authused = SASL_MECH_CRAM_MD5;
|
||||
}
|
||||
@@ -562,7 +573,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
#ifdef USE_NTLM
|
||||
if((imapc->authmechs & SASL_MECH_NTLM) &&
|
||||
(imapc->prefmech & SASL_MECH_NTLM)) {
|
||||
mech = "NTLM";
|
||||
mech = SASL_MECH_STRING_NTLM;
|
||||
state1 = IMAP_AUTHENTICATE_NTLM;
|
||||
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
|
||||
imapc->authused = SASL_MECH_NTLM;
|
||||
@@ -574,9 +585,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if((imapc->authmechs & SASL_MECH_LOGIN) &&
|
||||
if(((imapc->authmechs & SASL_MECH_XOAUTH2) &&
|
||||
(imapc->prefmech & SASL_MECH_XOAUTH2) &&
|
||||
(imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
|
||||
mech = SASL_MECH_STRING_XOAUTH2;
|
||||
state1 = IMAP_AUTHENTICATE_XOAUTH2;
|
||||
state2 = IMAP_AUTHENTICATE_FINAL;
|
||||
imapc->authused = SASL_MECH_XOAUTH2;
|
||||
|
||||
if(imapc->ir_supported || data->set.sasl_ir)
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&initresp, &len);
|
||||
}
|
||||
else if((imapc->authmechs & SASL_MECH_LOGIN) &&
|
||||
(imapc->prefmech & SASL_MECH_LOGIN)) {
|
||||
mech = "LOGIN";
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
state1 = IMAP_AUTHENTICATE_LOGIN;
|
||||
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
|
||||
imapc->authused = SASL_MECH_LOGIN;
|
||||
@@ -587,7 +611,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else if((imapc->authmechs & SASL_MECH_PLAIN) &&
|
||||
(imapc->prefmech & SASL_MECH_PLAIN)) {
|
||||
mech = "PLAIN";
|
||||
mech = SASL_MECH_STRING_PLAIN;
|
||||
state1 = IMAP_AUTHENTICATE_PLAIN;
|
||||
state2 = IMAP_AUTHENTICATE_FINAL;
|
||||
imapc->authused = SASL_MECH_PLAIN;
|
||||
@@ -638,7 +662,7 @@ static CURLcode imap_perform_list(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
char *mailbox;
|
||||
|
||||
if(imap->custom)
|
||||
@@ -673,7 +697,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
char *mailbox;
|
||||
|
||||
@@ -712,7 +736,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
|
||||
static CURLcode imap_perform_fetch(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
|
||||
/* Check we have a UID */
|
||||
if(!imap->uid) {
|
||||
@@ -740,7 +764,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
|
||||
static CURLcode imap_perform_append(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
char *mailbox;
|
||||
|
||||
/* Check we have a mailbox */
|
||||
@@ -864,20 +888,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
|
||||
wordlen -= 5;
|
||||
|
||||
/* Test the word for a matching authentication mechanism */
|
||||
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
|
||||
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
|
||||
imapc->authmechs |= SASL_MECH_LOGIN;
|
||||
if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
|
||||
imapc->authmechs |= SASL_MECH_PLAIN;
|
||||
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
|
||||
imapc->authmechs |= SASL_MECH_CRAM_MD5;
|
||||
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
|
||||
imapc->authmechs |= SASL_MECH_DIGEST_MD5;
|
||||
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
|
||||
imapc->authmechs |= SASL_MECH_GSSAPI;
|
||||
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
|
||||
imapc->authmechs |= SASL_MECH_EXTERNAL;
|
||||
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
imapc->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
imapc->authmechs |= SASL_MECH_XOAUTH2;
|
||||
}
|
||||
|
||||
line += wordlen;
|
||||
@@ -1243,6 +1269,44 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For AUTH XOAUTH2 (without initial response) responses */
|
||||
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||
int imapcode,
|
||||
imapstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *xoauth = NULL;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(imapcode != '+') {
|
||||
failf(data, "Access denied: %d", imapcode);
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For final responses to the AUTHENTICATE sequence */
|
||||
static CURLcode imap_state_auth_final_resp(struct connectdata *conn,
|
||||
int imapcode,
|
||||
@@ -1316,7 +1380,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
const char *line = data->state.buffer;
|
||||
char tmp[20];
|
||||
@@ -1407,10 +1471,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
|
||||
return result;
|
||||
|
||||
data->req.bytecount += chunk;
|
||||
size -= chunk;
|
||||
|
||||
infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU
|
||||
" bytes are left for transfer\n", (curl_off_t)chunk, size);
|
||||
" bytes are left for transfer\n", (curl_off_t)chunk,
|
||||
size - chunk);
|
||||
|
||||
/* Have we used the entire cache or just part of it?*/
|
||||
if(pp->cache_size > chunk) {
|
||||
@@ -1427,7 +1491,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
|
||||
}
|
||||
}
|
||||
|
||||
if(!size)
|
||||
if(data->req.bytecount == size)
|
||||
/* The entire data is already transferred! */
|
||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||
else {
|
||||
@@ -1592,6 +1656,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IMAP_AUTHENTICATE_XOAUTH2:
|
||||
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
|
||||
case IMAP_AUTHENTICATE_FINAL:
|
||||
result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
@@ -1642,11 +1710,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
|
||||
CURLcode result = CURLE_OK;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone)
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
|
||||
else
|
||||
result = Curl_pp_statemach(&imapc->pp, FALSE);
|
||||
if(result || !imapc->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_pp_statemach(&imapc->pp, FALSE);
|
||||
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
|
||||
|
||||
return result;
|
||||
@@ -1669,13 +1739,11 @@ static CURLcode imap_init(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap;
|
||||
|
||||
if(!imap) {
|
||||
imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1);
|
||||
imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
|
||||
if(!imap)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1705,15 +1773,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to not done yet */
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
/* Initialise the IMAP layer */
|
||||
result = imap_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* We always support persistent connections in IMAP */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
@@ -1759,7 +1818,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
|
||||
(void)premature;
|
||||
|
||||
@@ -1824,7 +1883,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
|
||||
/* This is IMAP and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
bool selected = FALSE;
|
||||
|
||||
@@ -1891,15 +1950,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to false */
|
||||
|
||||
/* Since connections can be re-used between SessionHandles, there might be a
|
||||
connection already existing but on a fresh SessionHandle struct. As such
|
||||
we make sure we have a good IMAP struct to play with. For new connections
|
||||
the IMAP struct is allocated and setup in the imap_connect() function. */
|
||||
Curl_reset_reqproto(conn);
|
||||
result = imap_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Parse the URL path */
|
||||
result = imap_parse_url_path(conn);
|
||||
if(result)
|
||||
@@ -1952,7 +2002,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
/* Call this when the DO phase has completed */
|
||||
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
|
||||
{
|
||||
struct IMAP *imap = conn->data->state.proto.imap;
|
||||
struct IMAP *imap = conn->data->req.protop;
|
||||
|
||||
(void)connected;
|
||||
|
||||
@@ -2018,6 +2068,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
/* Initialise the IMAP layer */
|
||||
CURLcode result = imap_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel IMAP operations through the proxy, we
|
||||
switch and use HTTP operations only */
|
||||
@@ -2033,10 +2088,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We explicitly mark this connection as persistent here as we're doing
|
||||
IMAP over HTTP and thus we accidentally avoid setting this value
|
||||
otherwise */
|
||||
conn->bits.close = FALSE;
|
||||
/* set it up as an HTTP connection instead */
|
||||
return conn->handler->setup_connection(conn);
|
||||
#else
|
||||
failf(data, "IMAP over http proxy requires HTTP support built-in!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
@@ -2225,18 +2278,20 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
|
||||
|
||||
if(strequal(value, "*"))
|
||||
imapc->prefmech = SASL_AUTH_ANY;
|
||||
else if(strequal(value, "LOGIN"))
|
||||
else if(strequal(value, SASL_MECH_STRING_LOGIN))
|
||||
imapc->prefmech = SASL_MECH_LOGIN;
|
||||
else if(strequal(value, "PLAIN"))
|
||||
else if(strequal(value, SASL_MECH_STRING_PLAIN))
|
||||
imapc->prefmech = SASL_MECH_PLAIN;
|
||||
else if(strequal(value, "CRAM-MD5"))
|
||||
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5))
|
||||
imapc->prefmech = SASL_MECH_CRAM_MD5;
|
||||
else if(strequal(value, "DIGEST-MD5"))
|
||||
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5))
|
||||
imapc->prefmech = SASL_MECH_DIGEST_MD5;
|
||||
else if(strequal(value, "GSSAPI"))
|
||||
else if(strequal(value, SASL_MECH_STRING_GSSAPI))
|
||||
imapc->prefmech = SASL_MECH_GSSAPI;
|
||||
else if(strequal(value, "NTLM"))
|
||||
else if(strequal(value, SASL_MECH_STRING_NTLM))
|
||||
imapc->prefmech = SASL_MECH_NTLM;
|
||||
else if(strequal(value, SASL_MECH_STRING_XOAUTH2))
|
||||
imapc->prefmech = SASL_MECH_XOAUTH2;
|
||||
else
|
||||
imapc->prefmech = SASL_AUTH_NONE;
|
||||
}
|
||||
@@ -2259,7 +2314,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
|
||||
/* The imap struct is already initialised in imap_connect() */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
const char *begin = data->state.path;
|
||||
const char *ptr = begin;
|
||||
|
||||
@@ -2367,7 +2422,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct IMAP *imap = data->state.proto.imap;
|
||||
struct IMAP *imap = data->req.protop;
|
||||
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
|
||||
|
||||
if(custom) {
|
||||
|
@@ -43,6 +43,7 @@ typedef enum {
|
||||
IMAP_AUTHENTICATE_DIGESTMD5_RESP,
|
||||
IMAP_AUTHENTICATE_NTLM,
|
||||
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
|
||||
IMAP_AUTHENTICATE_XOAUTH2,
|
||||
IMAP_AUTHENTICATE_FINAL,
|
||||
IMAP_LOGIN,
|
||||
IMAP_LIST,
|
||||
|
440
lib/krb4.c
440
lib/krb4.c
@@ -1,440 +0,0 @@
|
||||
/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
|
||||
* use in Curl. Martin's latest changes were done 2000-09-18.
|
||||
*
|
||||
* It has since been patched away like a madman by Daniel Stenberg to make it
|
||||
* better applied to curl conditions, and to make it not use globals, pollute
|
||||
* name space and more.
|
||||
*
|
||||
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* Copyright (c) 2004 - 2011 Daniel Stenberg
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
#ifdef HAVE_KRB4
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <krb.h>
|
||||
#include <des.h>
|
||||
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "ftp.h"
|
||||
#include "sendf.h"
|
||||
#include "krb4.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#define LOCAL_ADDR (&conn->local_addr)
|
||||
#define REMOTE_ADDR conn->ip_addr->ai_addr
|
||||
#define myctladdr LOCAL_ADDR
|
||||
#define hisctladdr REMOTE_ADDR
|
||||
|
||||
struct krb4_data {
|
||||
des_cblock key;
|
||||
des_key_schedule schedule;
|
||||
char name[ANAME_SZ];
|
||||
char instance[INST_SZ];
|
||||
char realm[REALM_SZ];
|
||||
};
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* if it ever goes non-static, make it Curl_ prefixed! */
|
||||
static size_t
|
||||
strlcpy (char *dst, const char *src, size_t dst_sz)
|
||||
{
|
||||
size_t n;
|
||||
char *p;
|
||||
|
||||
for(p = dst, n = 0;
|
||||
n + 1 < dst_sz && *src != '\0';
|
||||
++p, ++src, ++n)
|
||||
*p = *src;
|
||||
*p = '\0';
|
||||
if(*src == '\0')
|
||||
return n;
|
||||
else
|
||||
return n + strlen (src);
|
||||
}
|
||||
#else
|
||||
size_t strlcpy (char *dst, const char *src, size_t dst_sz);
|
||||
#endif
|
||||
|
||||
static int
|
||||
krb4_check_prot(void *app_data, int level)
|
||||
{
|
||||
app_data = NULL; /* prevent compiler warning */
|
||||
if(level == PROT_CONFIDENTIAL)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
krb4_decode(void *app_data, void *buf, int len, int level,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
MSG_DAT m;
|
||||
int e;
|
||||
struct krb4_data *d = app_data;
|
||||
|
||||
if(level == PROT_SAFE)
|
||||
e = krb_rd_safe(buf, len, &d->key,
|
||||
(struct sockaddr_in *)REMOTE_ADDR,
|
||||
(struct sockaddr_in *)LOCAL_ADDR, &m);
|
||||
else
|
||||
e = krb_rd_priv(buf, len, d->schedule, &d->key,
|
||||
(struct sockaddr_in *)REMOTE_ADDR,
|
||||
(struct sockaddr_in *)LOCAL_ADDR, &m);
|
||||
if(e) {
|
||||
struct SessionHandle *data = conn->data;
|
||||
infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
|
||||
return -1;
|
||||
}
|
||||
memmove(buf, m.app_data, m.app_length);
|
||||
return m.app_length;
|
||||
}
|
||||
|
||||
static int
|
||||
krb4_overhead(void *app_data, int level, int len)
|
||||
{
|
||||
/* no arguments are used, just init them to prevent compiler warnings */
|
||||
app_data = NULL;
|
||||
level = 0;
|
||||
len = 0;
|
||||
return 31;
|
||||
}
|
||||
|
||||
static int
|
||||
krb4_encode(void *app_data, const void *from, int length, int level, void **to,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct krb4_data *d = app_data;
|
||||
*to = malloc(length + 31);
|
||||
if(!*to)
|
||||
return -1;
|
||||
if(level == PROT_SAFE)
|
||||
/* NOTE that the void* cast is safe, krb_mk_safe/priv don't modify the
|
||||
* input buffer
|
||||
*/
|
||||
return krb_mk_safe((void*)from, *to, length, &d->key,
|
||||
(struct sockaddr_in *)LOCAL_ADDR,
|
||||
(struct sockaddr_in *)REMOTE_ADDR);
|
||||
else if(level == PROT_PRIVATE)
|
||||
return krb_mk_priv((void*)from, *to, length, d->schedule, &d->key,
|
||||
(struct sockaddr_in *)LOCAL_ADDR,
|
||||
(struct sockaddr_in *)REMOTE_ADDR);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mk_auth(struct krb4_data *d, KTEXT adat,
|
||||
const char *service, char *host, int checksum)
|
||||
{
|
||||
int ret;
|
||||
CREDENTIALS cred;
|
||||
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
|
||||
|
||||
strlcpy(sname, service, sizeof(sname));
|
||||
strlcpy(inst, krb_get_phost(host), sizeof(inst));
|
||||
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
|
||||
ret = krb_mk_req(adat, sname, inst, realm, checksum);
|
||||
if(ret)
|
||||
return ret;
|
||||
strlcpy(sname, service, sizeof(sname));
|
||||
strlcpy(inst, krb_get_phost(host), sizeof(inst));
|
||||
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
|
||||
ret = krb_get_cred(sname, inst, realm, &cred);
|
||||
memmove(&d->key, &cred.session, sizeof(des_cblock));
|
||||
des_key_sched(&d->key, d->schedule);
|
||||
memset(&cred, 0, sizeof(cred));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
|
||||
int krb_get_our_ip_for_realm(char *, struct in_addr *);
|
||||
#endif
|
||||
|
||||
static int
|
||||
krb4_auth(void *app_data, struct connectdata *conn)
|
||||
{
|
||||
int ret;
|
||||
char *p;
|
||||
unsigned char *ptr;
|
||||
size_t len = 0;
|
||||
KTEXT_ST adat;
|
||||
MSG_DAT msg_data;
|
||||
int checksum;
|
||||
u_int32_t cs;
|
||||
struct krb4_data *d = app_data;
|
||||
char *host = conn->host.name;
|
||||
ssize_t nread;
|
||||
int l = sizeof(conn->local_addr);
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result;
|
||||
size_t base64_sz = 0;
|
||||
|
||||
if(getsockname(conn->sock[FIRSTSOCKET],
|
||||
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
|
||||
perror("getsockname()");
|
||||
|
||||
checksum = getpid();
|
||||
ret = mk_auth(d, &adat, "ftp", host, checksum);
|
||||
if(ret == KDC_PR_UNKNOWN)
|
||||
ret = mk_auth(d, &adat, "rcmd", host, checksum);
|
||||
if(ret) {
|
||||
infof(data, "%s\n", krb_get_err_text(ret));
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
|
||||
if(krb_get_config_bool("nat_in_use")) {
|
||||
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
||||
struct in_addr natAddr;
|
||||
|
||||
if(krb_get_our_ip_for_realm(krb_realmofhost(host),
|
||||
&natAddr) != KSUCCESS
|
||||
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
|
||||
infof(data, "Can't get address for realm %s\n",
|
||||
krb_realmofhost(host));
|
||||
else {
|
||||
if(natAddr.s_addr != localaddr->sin_addr.s_addr) {
|
||||
char addr_buf[128];
|
||||
if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf)))
|
||||
infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf);
|
||||
localaddr->sin_addr = natAddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
result = Curl_base64_encode(conn->data, (char *)adat.dat, adat.length,
|
||||
&p, &base64_sz);
|
||||
if(result) {
|
||||
Curl_failf(data, "base64-encoding: %s", curl_easy_strerror(result));
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
result = Curl_ftpsendf(conn, "ADAT %s", p);
|
||||
|
||||
free(p);
|
||||
|
||||
if(result)
|
||||
return -2;
|
||||
|
||||
if(Curl_GetFTPResponse(&nread, conn, NULL))
|
||||
return -1;
|
||||
|
||||
if(data->state.buffer[0] != '2') {
|
||||
Curl_failf(data, "Server didn't accept auth data");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
|
||||
p = strstr(data->state.buffer, "ADAT=");
|
||||
if(!p) {
|
||||
Curl_failf(data, "Remote host didn't send adat reply");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
p += 5;
|
||||
result = Curl_base64_decode(p, &ptr, &len);
|
||||
if(result) {
|
||||
Curl_failf(data, "base64-decoding: %s", curl_easy_strerror(result));
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
if(len > sizeof(adat.dat)-1) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
len = 0;
|
||||
}
|
||||
if(!len || !ptr) {
|
||||
Curl_failf(data, "Failed to decode base64 from server");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
memcpy((char *)adat.dat, ptr, len);
|
||||
free(ptr);
|
||||
adat.length = len;
|
||||
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
|
||||
(struct sockaddr_in *)hisctladdr,
|
||||
(struct sockaddr_in *)myctladdr, &msg_data);
|
||||
if(ret) {
|
||||
Curl_failf(data, "Error reading reply from server: %s",
|
||||
krb_get_err_text(ret));
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
krb_get_int(msg_data.app_data, &cs, 4, 0);
|
||||
if(cs - checksum != 1) {
|
||||
Curl_failf(data, "Bad checksum returned from server");
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
return AUTH_OK;
|
||||
}
|
||||
|
||||
struct Curl_sec_client_mech Curl_krb4_client_mech = {
|
||||
"KERBEROS_V4",
|
||||
sizeof(struct krb4_data),
|
||||
NULL, /* init */
|
||||
krb4_auth,
|
||||
NULL, /* end */
|
||||
krb4_check_prot,
|
||||
krb4_overhead,
|
||||
krb4_encode,
|
||||
krb4_decode
|
||||
};
|
||||
|
||||
static enum protection_level
|
||||
krb4_set_command_prot(struct connectdata *conn, enum protection_level level)
|
||||
{
|
||||
enum protection_level old = conn->command_prot;
|
||||
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
|
||||
conn->command_prot = level;
|
||||
return old;
|
||||
}
|
||||
|
||||
CURLcode Curl_krb_kauth(struct connectdata *conn)
|
||||
{
|
||||
des_cblock key;
|
||||
des_key_schedule schedule;
|
||||
KTEXT_ST tkt, tktcopy;
|
||||
char *name;
|
||||
char *p;
|
||||
char passwd[100];
|
||||
size_t tmp = 0;
|
||||
ssize_t nread;
|
||||
enum protection_level save;
|
||||
CURLcode result;
|
||||
unsigned char *ptr;
|
||||
size_t base64_sz = 0;
|
||||
|
||||
save = krb4_set_command_prot(conn, PROT_PRIVATE);
|
||||
|
||||
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, NULL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->data->state.buffer[0] != '3') {
|
||||
krb4_set_command_prot(conn, save);
|
||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
|
||||
p = strstr(conn->data->state.buffer, "T=");
|
||||
if(!p) {
|
||||
Curl_failf(conn->data, "Bad reply from server");
|
||||
krb4_set_command_prot(conn, save);
|
||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
|
||||
p += 2;
|
||||
result = Curl_base64_decode(p, &ptr, &tmp);
|
||||
if(result) {
|
||||
Curl_failf(conn->data, "base64-decoding: %s", curl_easy_strerror(result));
|
||||
return result;
|
||||
}
|
||||
if(tmp >= sizeof(tkt.dat)) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
tmp = 0;
|
||||
}
|
||||
if(!tmp || !ptr) {
|
||||
Curl_failf(conn->data, "Failed to decode base64 in reply");
|
||||
krb4_set_command_prot(conn, save);
|
||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
memcpy((char *)tkt.dat, ptr, tmp);
|
||||
free(ptr);
|
||||
tkt.length = tmp;
|
||||
tktcopy.length = tkt.length;
|
||||
|
||||
p = strstr(conn->data->state.buffer, "P=");
|
||||
if(!p) {
|
||||
Curl_failf(conn->data, "Bad reply from server");
|
||||
krb4_set_command_prot(conn, save);
|
||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
name = p + 2;
|
||||
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
|
||||
*p = 0;
|
||||
|
||||
des_string_to_key (conn->passwd, &key);
|
||||
des_key_sched(&key, schedule);
|
||||
|
||||
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
|
||||
tkt.length,
|
||||
schedule, &key, DES_DECRYPT);
|
||||
if(strcmp ((char*)tktcopy.dat + 8,
|
||||
KRB_TICKET_GRANTING_TICKET) != 0) {
|
||||
afs_string_to_key(passwd,
|
||||
krb_realmofhost(conn->host.name),
|
||||
&key);
|
||||
des_key_sched(&key, schedule);
|
||||
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
|
||||
tkt.length,
|
||||
schedule, &key, DES_DECRYPT);
|
||||
}
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(schedule, 0, sizeof(schedule));
|
||||
memset(passwd, 0, sizeof(passwd));
|
||||
result = Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length,
|
||||
&p, &base64_sz);
|
||||
if(result) {
|
||||
Curl_failf(conn->data, "base64-encoding: %s", curl_easy_strerror(result));
|
||||
krb4_set_command_prot(conn, save);
|
||||
return result;
|
||||
}
|
||||
memset (tktcopy.dat, 0, tktcopy.length);
|
||||
|
||||
result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p);
|
||||
free(p);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, NULL);
|
||||
if(result)
|
||||
return result;
|
||||
krb4_set_command_prot(conn, save);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* HAVE_KRB4 */
|
||||
#endif /* CURL_DISABLE_FTP */
|
@@ -1,6 +1,6 @@
|
||||
/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
|
||||
*
|
||||
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
|
||||
* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2013 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* Copyright (c) 2004 - 2012 Daniel Stenberg
|
||||
* All rights reserved.
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "ftp.h"
|
||||
#include "curl_gssapi.h"
|
||||
#include "sendf.h"
|
||||
#include "krb4.h"
|
||||
#include "curl_sec.h"
|
||||
#include "curl_memory.h"
|
||||
#include "warnless.h"
|
||||
|
||||
|
45
lib/ldap.c
45
lib/ldap.c
@@ -84,6 +84,9 @@ typedef struct {
|
||||
int lud_scope;
|
||||
char *lud_filter;
|
||||
char **lud_exts;
|
||||
size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
|
||||
"real" struct so can only be used in code
|
||||
without HAVE_LDAP_URL_PARSE defined */
|
||||
} CURL_LDAPURLDesc;
|
||||
|
||||
#undef LDAPURLDesc
|
||||
@@ -539,19 +542,15 @@ static bool unescape_elements (void *data, LDAPURLDesc *ludp)
|
||||
if(ludp->lud_filter) {
|
||||
ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
|
||||
if(!ludp->lud_filter)
|
||||
return (FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for(i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
|
||||
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL);
|
||||
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i],
|
||||
0, NULL);
|
||||
if(!ludp->lud_attrs[i])
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
for(i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
|
||||
ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL);
|
||||
if(!ludp->lud_exts[i])
|
||||
return (FALSE);
|
||||
return FALSE;
|
||||
ludp->lud_attrs_dups++;
|
||||
}
|
||||
|
||||
if(ludp->lud_dn) {
|
||||
@@ -637,8 +636,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||
|
||||
if(*p && *p != '?') {
|
||||
ludp->lud_scope = str2scope(p);
|
||||
if(ludp->lud_scope == -1)
|
||||
if(ludp->lud_scope == -1) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
LDAP_TRACE (("scope %d\n", ludp->lud_scope));
|
||||
}
|
||||
|
||||
@@ -651,25 +651,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||
q = strchr(p, '?');
|
||||
if(q)
|
||||
*q++ = '\0';
|
||||
if(!*p)
|
||||
if(!*p) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
ludp->lud_filter = p;
|
||||
LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
|
||||
|
||||
p = q;
|
||||
if(!p)
|
||||
goto success;
|
||||
|
||||
/* parse extensions
|
||||
*/
|
||||
ludp->lud_exts = split_str(p);
|
||||
if(!ludp->lud_exts)
|
||||
return LDAP_NO_MEMORY;
|
||||
|
||||
for(i = 0; ludp->lud_exts[i]; i++)
|
||||
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
|
||||
|
||||
success:
|
||||
if(!unescape_elements(conn->data, ludp))
|
||||
return LDAP_NO_MEMORY;
|
||||
@@ -697,7 +685,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
|
||||
|
||||
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
if(!ludp)
|
||||
return;
|
||||
@@ -709,16 +697,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp)
|
||||
free(ludp->lud_filter);
|
||||
|
||||
if(ludp->lud_attrs) {
|
||||
for(i = 0; ludp->lud_attrs[i]; i++)
|
||||
for(i = 0; i < ludp->lud_attrs_dups; i++)
|
||||
free(ludp->lud_attrs[i]);
|
||||
free(ludp->lud_attrs);
|
||||
}
|
||||
|
||||
if(ludp->lud_exts) {
|
||||
for(i = 0; ludp->lud_exts[i]; i++)
|
||||
free(ludp->lud_exts[i]);
|
||||
free(ludp->lud_exts);
|
||||
}
|
||||
free (ludp);
|
||||
}
|
||||
#endif /* !HAVE_LDAP_URL_PARSE */
|
||||
|
679
lib/multi.c
679
lib/multi.c
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,13 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/* See multi_socket() for the explanation of this constant. Counted in number
|
||||
of microseconds. */
|
||||
#ifdef WIN32
|
||||
#define MULTI_TIMEOUT_INACCURACY 40000
|
||||
#else
|
||||
#define MULTI_TIMEOUT_INACCURACY 3000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
|
25
lib/netrc.c
25
lib/netrc.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
|
||||
@@ -50,15 +50,18 @@ enum host_lookup_state {
|
||||
|
||||
/*
|
||||
* @unittest: 1304
|
||||
*
|
||||
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
|
||||
* in.
|
||||
*/
|
||||
int Curl_parsenetrc(const char *host,
|
||||
char *login,
|
||||
char *password,
|
||||
char **loginp,
|
||||
char **passwordp,
|
||||
char *netrcfile)
|
||||
{
|
||||
FILE *file;
|
||||
int retcode=1;
|
||||
int specific_login = (login[0] != 0);
|
||||
int specific_login = (**loginp != 0);
|
||||
char *home = NULL;
|
||||
bool home_alloc = FALSE;
|
||||
bool netrc_alloc = FALSE;
|
||||
@@ -109,7 +112,7 @@ int Curl_parsenetrc(const char *host,
|
||||
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
|
||||
while(!done && tok) {
|
||||
|
||||
if(login[0] && password[0]) {
|
||||
if(**loginp && **passwordp) {
|
||||
done=TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -138,16 +141,22 @@ int Curl_parsenetrc(const char *host,
|
||||
/* we are now parsing sub-keywords concerning "our" host */
|
||||
if(state_login) {
|
||||
if(specific_login) {
|
||||
state_our_login = Curl_raw_equal(login, tok);
|
||||
state_our_login = Curl_raw_equal(*loginp, tok);
|
||||
}
|
||||
else {
|
||||
strncpy(login, tok, LOGINSIZE-1);
|
||||
free(*loginp);
|
||||
*loginp = strdup(tok);
|
||||
if(!*loginp)
|
||||
return -1; /* allocation failed */
|
||||
}
|
||||
state_login=0;
|
||||
}
|
||||
else if(state_password) {
|
||||
if(state_our_login || !specific_login) {
|
||||
strncpy(password, tok, PASSWORDSIZE-1);
|
||||
free(*passwordp);
|
||||
*passwordp = strdup(tok);
|
||||
if(!*passwordp)
|
||||
return -1; /* allocation failed */
|
||||
}
|
||||
state_password=0;
|
||||
}
|
||||
|
16
lib/netrc.h
16
lib/netrc.h
@@ -22,19 +22,15 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* Make sure we have room for at least this size: */
|
||||
#define LOGINSIZE 64
|
||||
#define PASSWORDSIZE 64
|
||||
|
||||
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
|
||||
int Curl_parsenetrc(const char *host,
|
||||
char *login,
|
||||
char *password,
|
||||
char **loginp,
|
||||
char **passwordp,
|
||||
char *filename);
|
||||
/* Assume: password[0]=0, host[0] != 0.
|
||||
* If login[0] = 0, search for login and password within a machine section
|
||||
* in the netrc.
|
||||
* If login[0] != 0, search for password within machine and login.
|
||||
/* Assume: (*passwordp)[0]=0, host[0] != 0.
|
||||
* If (*loginp)[0] = 0, search for login and password within a machine
|
||||
* section in the netrc.
|
||||
* If (*loginp)[0] != 0, search for password within machine and login.
|
||||
*/
|
||||
|
||||
#endif /* HEADER_CURL_NETRC_H */
|
||||
|
11
lib/nss.c
11
lib/nss.c
@@ -1543,9 +1543,8 @@ size_t Curl_nss_version(char *buffer, size_t size)
|
||||
|
||||
int Curl_nss_seed(struct SessionHandle *data)
|
||||
{
|
||||
/* TODO: implement? */
|
||||
(void) data;
|
||||
return 0;
|
||||
/* make sure that NSS is initialized */
|
||||
return !!Curl_nss_force_init(data);
|
||||
}
|
||||
|
||||
void Curl_nss_random(struct SessionHandle *data,
|
||||
@@ -1553,7 +1552,11 @@ void Curl_nss_random(struct SessionHandle *data,
|
||||
size_t length)
|
||||
{
|
||||
Curl_nss_seed(data); /* Initiate the seed if not already done */
|
||||
PK11_GenerateRandom(entropy, curlx_uztosi(length));
|
||||
if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
|
||||
/* no way to signal a failure from here, we have to abort */
|
||||
failf(data, "PK11_GenerateRandom() failed, calling abort()...");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_nss_md5sum(unsigned char *tmp, /* input */
|
||||
|
@@ -378,7 +378,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
|
||||
if(!lr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
lr->msgid = msgid;
|
||||
data->state.proto.generic = lr;
|
||||
data->req.protop = lr;
|
||||
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
@@ -387,7 +387,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
|
||||
static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
|
||||
bool premature)
|
||||
{
|
||||
ldapreqinfo *lr = conn->data->state.proto.generic;
|
||||
ldapreqinfo *lr = conn->data->req.protop;
|
||||
(void)res;
|
||||
(void)premature;
|
||||
|
||||
@@ -398,7 +398,7 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
|
||||
ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
|
||||
lr->msgid = 0;
|
||||
}
|
||||
conn->data->state.proto.generic = NULL;
|
||||
conn->data->req.protop = NULL;
|
||||
free(lr);
|
||||
}
|
||||
return CURLE_OK;
|
||||
@@ -409,7 +409,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
|
||||
{
|
||||
ldapconninfo *li = conn->proto.generic;
|
||||
struct SessionHandle *data=conn->data;
|
||||
ldapreqinfo *lr = data->state.proto.generic;
|
||||
ldapreqinfo *lr = data->req.protop;
|
||||
int rc, ret;
|
||||
LDAPMessage *result = NULL;
|
||||
LDAPMessage *ent;
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "pingpong.h"
|
||||
#include "multiif.h"
|
||||
#include "non-ascii.h"
|
||||
#include "sslgen.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -105,6 +106,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
|
||||
if(Curl_pp_moredata(pp))
|
||||
/* We are receiving and there is data in the cache so just read it */
|
||||
rc = 1;
|
||||
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
||||
/* We are receiving and there is data ready in the SSL library */
|
||||
rc = 1;
|
||||
else
|
||||
rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
|
||||
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
|
||||
@@ -165,7 +169,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
|
||||
struct connectdata *conn = pp->conn;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
enum protection_level data_sec = conn->data_prot;
|
||||
#endif
|
||||
|
||||
@@ -194,12 +198,12 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
|
||||
return error;
|
||||
}
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
|
||||
&bytes_written);
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
|
||||
conn->data_prot = data_sec;
|
||||
#endif
|
||||
@@ -302,14 +306,14 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
enum protection_level prot = conn->data_prot;
|
||||
conn->data_prot = PROT_CLEAR;
|
||||
#endif
|
||||
DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
|
||||
res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
|
||||
&gotbytes);
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
|
||||
conn->data_prot = prot;
|
||||
#endif
|
||||
@@ -352,7 +356,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
the line isn't really terminated until the LF comes */
|
||||
|
||||
/* output debug output if that is requested */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
if(!conn->sec_complete)
|
||||
#endif
|
||||
if(data->set.verbose)
|
||||
@@ -371,8 +375,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
|
||||
if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
|
||||
/* This is the end of the last line, copy the last line to the
|
||||
start of the buffer and zero terminate, for old times sake (and
|
||||
krb4)! */
|
||||
start of the buffer and zero terminate, for old times sake */
|
||||
char *meow;
|
||||
int n;
|
||||
for(meow=pp->linestart_resp, n=0; meow<ptr; meow++, n++)
|
||||
|
159
lib/pop3.c
159
lib/pop3.c
@@ -28,6 +28,7 @@
|
||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC5034 POP3 SASL Authentication Mechanism
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
@@ -163,7 +164,7 @@ const struct Curl_handler Curl_handler_pop3s = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_pop3_proxy = {
|
||||
"POP3", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -188,7 +189,7 @@ static const struct Curl_handler Curl_handler_pop3_proxy = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_pop3s_proxy = {
|
||||
"POP3S", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -312,20 +313,22 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
wordlen++;
|
||||
|
||||
/* Test the word for a matching authentication mechanism */
|
||||
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
|
||||
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
|
||||
pop3c->authmechs |= SASL_MECH_LOGIN;
|
||||
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
|
||||
pop3c->authmechs |= SASL_MECH_PLAIN;
|
||||
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
|
||||
pop3c->authmechs |= SASL_MECH_CRAM_MD5;
|
||||
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
|
||||
pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
|
||||
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
|
||||
pop3c->authmechs |= SASL_MECH_GSSAPI;
|
||||
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
|
||||
pop3c->authmechs |= SASL_MECH_EXTERNAL;
|
||||
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
pop3c->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
pop3c->authmechs |= SASL_MECH_XOAUTH2;
|
||||
|
||||
line += wordlen;
|
||||
len -= wordlen;
|
||||
@@ -371,6 +374,7 @@ static void state(struct connectdata *conn, pop3state newstate)
|
||||
"AUTH_DIGESTMD5_RESP",
|
||||
"AUTH_NTLM",
|
||||
"AUTH_NTLM_TYPE2MSG",
|
||||
"AUTH_XOAUTH2",
|
||||
"AUTH_FINAL",
|
||||
"APOP",
|
||||
"USER",
|
||||
@@ -572,13 +576,13 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||
mech = "DIGEST-MD5";
|
||||
mech = SASL_MECH_STRING_DIGEST_MD5;
|
||||
state1 = POP3_AUTH_DIGESTMD5;
|
||||
pop3c->authused = SASL_MECH_DIGEST_MD5;
|
||||
}
|
||||
else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||
(pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||
mech = "CRAM-MD5";
|
||||
mech = SASL_MECH_STRING_CRAM_MD5;
|
||||
state1 = POP3_AUTH_CRAMMD5;
|
||||
pop3c->authused = SASL_MECH_CRAM_MD5;
|
||||
}
|
||||
@@ -587,7 +591,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||
#ifdef USE_NTLM
|
||||
if((pop3c->authmechs & SASL_MECH_NTLM) &&
|
||||
(pop3c->prefmech & SASL_MECH_NTLM)) {
|
||||
mech = "NTLM";
|
||||
mech = SASL_MECH_STRING_NTLM;
|
||||
state1 = POP3_AUTH_NTLM;
|
||||
state2 = POP3_AUTH_NTLM_TYPE2MSG;
|
||||
pop3c->authused = SASL_MECH_NTLM;
|
||||
@@ -599,9 +603,22 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if((pop3c->authmechs & SASL_MECH_LOGIN) &&
|
||||
if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
|
||||
(pop3c->prefmech & SASL_MECH_XOAUTH2) &&
|
||||
(pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
|
||||
mech = SASL_MECH_STRING_XOAUTH2;
|
||||
state1 = POP3_AUTH_XOAUTH2;
|
||||
state2 = POP3_AUTH_FINAL;
|
||||
pop3c->authused = SASL_MECH_XOAUTH2;
|
||||
|
||||
if(data->set.sasl_ir)
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&initresp, &len);
|
||||
}
|
||||
else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
|
||||
(pop3c->prefmech & SASL_MECH_LOGIN)) {
|
||||
mech = "LOGIN";
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
state1 = POP3_AUTH_LOGIN;
|
||||
state2 = POP3_AUTH_LOGIN_PASSWD;
|
||||
pop3c->authused = SASL_MECH_LOGIN;
|
||||
@@ -612,7 +629,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
|
||||
(pop3c->prefmech & SASL_MECH_PLAIN)) {
|
||||
mech = "PLAIN";
|
||||
mech = SASL_MECH_STRING_PLAIN;
|
||||
state1 = POP3_AUTH_PLAIN;
|
||||
state2 = POP3_AUTH_FINAL;
|
||||
pop3c->authused = SASL_MECH_PLAIN;
|
||||
@@ -673,7 +690,7 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3 = data->req.protop;
|
||||
const char *command = NULL;
|
||||
|
||||
/* Calculate the default command */
|
||||
@@ -1110,6 +1127,43 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For AUTH XOAUTH2 (without initial response) responses */
|
||||
static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||
int pop3code, pop3state instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *xoauth = NULL;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(pop3code != '+') {
|
||||
failf(data, "Access denied: %d", pop3code);
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For final responses to the AUTH sequence */
|
||||
static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
|
||||
int pop3code,
|
||||
@@ -1203,7 +1257,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3 = data->req.protop;
|
||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||
struct pingpong *pp = &pop3c->pp;
|
||||
|
||||
@@ -1328,6 +1382,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case POP3_AUTH_XOAUTH2:
|
||||
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
|
||||
break;
|
||||
|
||||
case POP3_AUTH_FINAL:
|
||||
result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
|
||||
break;
|
||||
@@ -1368,11 +1426,13 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
|
||||
CURLcode result = CURLE_OK;
|
||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone)
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
|
||||
else
|
||||
result = Curl_pp_statemach(&pop3c->pp, FALSE);
|
||||
if(result || !pop3c->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_pp_statemach(&pop3c->pp, FALSE);
|
||||
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
|
||||
|
||||
return result;
|
||||
@@ -1395,13 +1455,11 @@ static CURLcode pop3_init(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3;
|
||||
|
||||
if(!pop3) {
|
||||
pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1);
|
||||
pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
|
||||
if(!pop3)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1431,15 +1489,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to not done yet */
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
/* Initialise the POP3 layer */
|
||||
result = pop3_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* We always support persistent connections in POP3 */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
@@ -1483,7 +1532,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3 = data->req.protop;
|
||||
|
||||
(void)premature;
|
||||
|
||||
@@ -1526,7 +1575,7 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
|
||||
|
||||
if(conn->data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
struct POP3 *pop3 = conn->data->state.proto.pop3;
|
||||
struct POP3 *pop3 = conn->data->req.protop;
|
||||
pop3->transfer = FTPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
@@ -1563,15 +1612,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to false */
|
||||
|
||||
/* Since connections can be re-used between SessionHandles, there might be a
|
||||
connection already existing but on a fresh SessionHandle struct. As such
|
||||
we make sure we have a good POP3 struct to play with. For new connections
|
||||
the POP3 struct is allocated and setup in the pop3_connect() function. */
|
||||
Curl_reset_reqproto(conn);
|
||||
result = pop3_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Parse the URL path */
|
||||
result = pop3_parse_url_path(conn);
|
||||
if(result)
|
||||
@@ -1685,6 +1725,11 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
/* Initialise the POP3 layer */
|
||||
CURLcode result = pop3_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel POP3 operations through the proxy, we
|
||||
switch and use HTTP operations only */
|
||||
@@ -1700,10 +1745,8 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We explicitly mark this connection as persistent here as we're doing
|
||||
POP3 over HTTP and thus we accidentally avoid setting this value
|
||||
otherwise */
|
||||
conn->bits.close = FALSE;
|
||||
/* set it up as an HTTP connection instead */
|
||||
return conn->handler->setup_connection(conn);
|
||||
#else
|
||||
failf(data, "POP3 over http proxy requires HTTP support built-in!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
@@ -1745,30 +1788,34 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
|
||||
pop3c->preftype = POP3_TYPE_APOP;
|
||||
pop3c->prefmech = SASL_AUTH_NONE;
|
||||
}
|
||||
else if(strequal(value, "LOGIN")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_LOGIN;
|
||||
}
|
||||
else if(strequal(value, "PLAIN")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_PLAIN;
|
||||
}
|
||||
else if(strequal(value, "CRAM-MD5")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_CRAM_MD5;
|
||||
}
|
||||
else if(strequal(value, "DIGEST-MD5")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_DIGEST_MD5;
|
||||
}
|
||||
else if(strequal(value, "GSSAPI")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_GSSAPI;
|
||||
}
|
||||
else if(strequal(value, "NTLM")) {
|
||||
else if(strequal(value, SASL_MECH_STRING_NTLM)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_NTLM;
|
||||
}
|
||||
else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
|
||||
pop3c->preftype = POP3_TYPE_SASL;
|
||||
pop3c->prefmech = SASL_MECH_XOAUTH2;
|
||||
}
|
||||
else {
|
||||
pop3c->preftype = POP3_TYPE_NONE;
|
||||
pop3c->prefmech = SASL_AUTH_NONE;
|
||||
@@ -1791,7 +1838,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
|
||||
{
|
||||
/* The POP3 struct is already initialised in pop3_connect() */
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3 = data->req.protop;
|
||||
const char *path = data->state.path;
|
||||
|
||||
/* URL decode the path for the message ID */
|
||||
@@ -1808,7 +1855,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct POP3 *pop3 = data->state.proto.pop3;
|
||||
struct POP3 *pop3 = data->req.protop;
|
||||
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
|
||||
|
||||
/* URL decode the custom request */
|
||||
|
@@ -43,6 +43,7 @@ typedef enum {
|
||||
POP3_AUTH_DIGESTMD5_RESP,
|
||||
POP3_AUTH_NTLM,
|
||||
POP3_AUTH_NTLM_TYPE2MSG,
|
||||
POP3_AUTH_XOAUTH2,
|
||||
POP3_AUTH_FINAL,
|
||||
POP3_APOP,
|
||||
POP3_USER,
|
||||
|
40
lib/rtsp.c
40
lib/rtsp.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
|
||||
@@ -81,6 +81,8 @@ static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
|
||||
ssize_t *nread,
|
||||
bool *readmore);
|
||||
|
||||
static CURLcode rtsp_setup_connection(struct connectdata *conn);
|
||||
|
||||
|
||||
/* this returns the socket to wait for in the DO and DOING state for the multi
|
||||
interface and then we're always _sending_ a request and thus we wait for
|
||||
@@ -104,7 +106,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_rtsp = {
|
||||
"RTSP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
rtsp_setup_connection, /* setup_connection */
|
||||
rtsp_do, /* do_it */
|
||||
rtsp_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -122,6 +124,19 @@ const struct Curl_handler Curl_handler_rtsp = {
|
||||
PROTOPT_NONE /* flags */
|
||||
};
|
||||
|
||||
|
||||
static CURLcode rtsp_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct RTSP *rtsp;
|
||||
|
||||
conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
|
||||
if(!rtsp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
|
||||
* want to block the application forever while receiving a stream. Therefore,
|
||||
@@ -185,7 +200,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct RTSP *rtsp = data->state.proto.rtsp;
|
||||
struct RTSP *rtsp = data->req.protop;
|
||||
CURLcode httpStatus;
|
||||
long CSeq_sent;
|
||||
long CSeq_recv;
|
||||
@@ -221,7 +236,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result=CURLE_OK;
|
||||
Curl_RtspReq rtspreq = data->set.rtspreq;
|
||||
struct RTSP *rtsp;
|
||||
struct RTSP *rtsp = data->req.protop;
|
||||
struct HTTP *http;
|
||||
Curl_send_buffer *req_buffer;
|
||||
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
|
||||
@@ -239,20 +254,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = TRUE;
|
||||
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
if(!data->state.proto.rtsp) {
|
||||
/* Only allocate this struct if we don't already have it! */
|
||||
|
||||
rtsp = calloc(1, sizeof(struct RTSP));
|
||||
if(!rtsp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->state.proto.rtsp = rtsp;
|
||||
}
|
||||
else {
|
||||
rtsp = data->state.proto.rtsp;
|
||||
}
|
||||
|
||||
http = &(rtsp->http_wrapper);
|
||||
/* Assert that no one has changed the RTSP struct in an evil way */
|
||||
DEBUGASSERT((void *)http == (void *)rtsp);
|
||||
@@ -749,7 +750,8 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
|
||||
/* Store the received CSeq. Match is verified in rtsp_done */
|
||||
int nc = sscanf(&header[4], ": %ld", &CSeq);
|
||||
if(nc == 1) {
|
||||
data->state.proto.rtsp->CSeq_recv = CSeq; /* mark the request */
|
||||
struct RTSP *rtsp = data->req.protop;
|
||||
rtsp->CSeq_recv = CSeq; /* mark the request */
|
||||
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
|
||||
}
|
||||
else {
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* rewrite to work around the paragraph 2 in the BSD licenses as explained
|
||||
* below.
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
|
||||
* Copyright (c) 1998, 1999, 2013 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
*
|
||||
* Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
@@ -57,7 +57,7 @@
|
||||
#include "urldata.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_memory.h"
|
||||
#include "krb4.h"
|
||||
#include "curl_sec.h"
|
||||
#include "ftp.h"
|
||||
#include "sendf.h"
|
||||
#include "rawstr.h"
|
||||
@@ -110,11 +110,8 @@ static char level_to_char(int level) {
|
||||
}
|
||||
|
||||
static const struct Curl_sec_client_mech * const mechs[] = {
|
||||
#if defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
&Curl_krb5_client_mech,
|
||||
#endif
|
||||
#if defined(HAVE_KRB4)
|
||||
&Curl_krb4_client_mech,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -199,7 +196,7 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
|
||||
|
||||
static CURLcode read_data(struct connectdata *conn,
|
||||
curl_socket_t fd,
|
||||
struct krb4buffer *buf)
|
||||
struct krb5buffer *buf)
|
||||
{
|
||||
int len;
|
||||
void* tmp;
|
||||
@@ -225,7 +222,7 @@ static CURLcode read_data(struct connectdata *conn,
|
||||
}
|
||||
|
||||
static size_t
|
||||
buffer_read(struct krb4buffer *buf, void *data, size_t len)
|
||||
buffer_read(struct krb5buffer *buf, void *data, size_t len)
|
||||
{
|
||||
if(buf->size - buf->index < len)
|
||||
len = buf->size - buf->index;
|
||||
@@ -599,6 +596,6 @@ Curl_sec_end(struct connectdata *conn)
|
||||
conn->mech = NULL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_KRB4 || HAVE_GSSAPI */
|
||||
#endif /* HAVE_GSSAPI */
|
||||
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
|
10
lib/sendf.c
10
lib/sendf.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
|
||||
@@ -35,14 +35,6 @@
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
|
||||
#if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
|
||||
#include "krb4.h"
|
||||
#else
|
||||
#define Curl_sec_send(a,b,c,d) -1
|
||||
#define Curl_sec_read(a,b,c,d) -1
|
||||
#endif
|
||||
|
||||
#include "curl_memory.h"
|
||||
#include "strerror.h"
|
||||
|
||||
|
160
lib/smtp.c
160
lib/smtp.c
@@ -26,6 +26,7 @@
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC4954 SMTP Authentication
|
||||
* RFC5321 SMTP protocol
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
* Draft SMTP URL Interface
|
||||
*
|
||||
***************************************************************************/
|
||||
@@ -161,7 +162,7 @@ const struct Curl_handler Curl_handler_smtps = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_smtp_proxy = {
|
||||
"SMTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -186,7 +187,7 @@ static const struct Curl_handler Curl_handler_smtp_proxy = {
|
||||
|
||||
static const struct Curl_handler Curl_handler_smtps_proxy = {
|
||||
"SMTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http_setup_conn, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -276,20 +277,22 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
wordlen++;
|
||||
|
||||
/* Test the word for a matching authentication mechanism */
|
||||
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
|
||||
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
|
||||
smtpc->authmechs |= SASL_MECH_LOGIN;
|
||||
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
|
||||
smtpc->authmechs |= SASL_MECH_PLAIN;
|
||||
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
|
||||
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
|
||||
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
|
||||
smtpc->authmechs |= SASL_MECH_GSSAPI;
|
||||
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
|
||||
smtpc->authmechs |= SASL_MECH_EXTERNAL;
|
||||
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
smtpc->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
smtpc->authmechs |= SASL_MECH_XOAUTH2;
|
||||
|
||||
line += wordlen;
|
||||
len -= wordlen;
|
||||
@@ -326,6 +329,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
|
||||
"AUTH_DIGESTMD5_RESP",
|
||||
"AUTH_NTLM",
|
||||
"AUTH_NTLM_TYPE2MSG",
|
||||
"AUTH_XOAUTH2",
|
||||
"AUTH_FINAL",
|
||||
"MAIL",
|
||||
"RCPT",
|
||||
@@ -469,13 +473,13 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
(smtpc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||
mech = "DIGEST-MD5";
|
||||
mech = SASL_MECH_STRING_DIGEST_MD5;
|
||||
state1 = SMTP_AUTH_DIGESTMD5;
|
||||
smtpc->authused = SASL_MECH_DIGEST_MD5;
|
||||
}
|
||||
else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||
(smtpc->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||
mech = "CRAM-MD5";
|
||||
mech = SASL_MECH_STRING_CRAM_MD5;
|
||||
state1 = SMTP_AUTH_CRAMMD5;
|
||||
smtpc->authused = SASL_MECH_CRAM_MD5;
|
||||
}
|
||||
@@ -484,7 +488,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||
#ifdef USE_NTLM
|
||||
if((smtpc->authmechs & SASL_MECH_NTLM) &&
|
||||
(smtpc->prefmech & SASL_MECH_NTLM)) {
|
||||
mech = "NTLM";
|
||||
mech = SASL_MECH_STRING_NTLM;
|
||||
state1 = SMTP_AUTH_NTLM;
|
||||
state2 = SMTP_AUTH_NTLM_TYPE2MSG;
|
||||
smtpc->authused = SASL_MECH_NTLM;
|
||||
@@ -496,9 +500,22 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if((smtpc->authmechs & SASL_MECH_LOGIN) &&
|
||||
if(((smtpc->authmechs & SASL_MECH_XOAUTH2) &&
|
||||
(smtpc->prefmech & SASL_MECH_XOAUTH2) &&
|
||||
(smtpc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
|
||||
mech = SASL_MECH_STRING_XOAUTH2;
|
||||
state1 = SMTP_AUTH_XOAUTH2;
|
||||
state2 = SMTP_AUTH_FINAL;
|
||||
smtpc->authused = SASL_MECH_XOAUTH2;
|
||||
|
||||
if(data->set.sasl_ir)
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&initresp, &len);
|
||||
}
|
||||
else if((smtpc->authmechs & SASL_MECH_LOGIN) &&
|
||||
(smtpc->prefmech & SASL_MECH_LOGIN)) {
|
||||
mech = "LOGIN";
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
state1 = SMTP_AUTH_LOGIN;
|
||||
state2 = SMTP_AUTH_LOGIN_PASSWD;
|
||||
smtpc->authused = SASL_MECH_LOGIN;
|
||||
@@ -509,7 +526,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||
}
|
||||
else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
|
||||
(smtpc->prefmech & SASL_MECH_PLAIN)) {
|
||||
mech = "PLAIN";
|
||||
mech = SASL_MECH_STRING_PLAIN;
|
||||
state1 = SMTP_AUTH_PLAIN;
|
||||
state2 = SMTP_AUTH_FINAL;
|
||||
smtpc->authused = SASL_MECH_PLAIN;
|
||||
@@ -636,7 +653,7 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
/* Send the RCPT TO command */
|
||||
if(smtp->rcpt) {
|
||||
@@ -1088,6 +1105,43 @@ static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For AUTH XOAUTH2 (without initial response) responses */
|
||||
static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||
int smtpcode, smtpstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *xoauth = NULL;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode != 334) {
|
||||
failf(data, "Access denied: %d", smtpcode);
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For the final responses to the AUTH sequence */
|
||||
static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
|
||||
int smtpcode,
|
||||
@@ -1115,7 +1169,7 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -1139,7 +1193,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -1296,6 +1350,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SMTP_AUTH_XOAUTH2:
|
||||
result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
|
||||
case SMTP_AUTH_FINAL:
|
||||
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
@@ -1334,11 +1392,13 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
|
||||
CURLcode result = CURLE_OK;
|
||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone)
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
|
||||
else
|
||||
result = Curl_pp_statemach(&smtpc->pp, FALSE);
|
||||
if(result || !smtpc->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_pp_statemach(&smtpc->pp, FALSE);
|
||||
*done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
|
||||
|
||||
return result;
|
||||
@@ -1361,13 +1421,11 @@ static CURLcode smtp_init(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp;
|
||||
|
||||
if(!smtp) {
|
||||
smtp = data->state.proto.smtp = calloc(sizeof(struct SMTP), 1);
|
||||
smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
|
||||
if(!smtp)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1397,15 +1455,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to not done yet */
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
/* Initialise the SMTP layer */
|
||||
result = smtp_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* We always support persistent connections in SMTP */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
@@ -1453,7 +1502,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
struct pingpong *pp = &conn->proto.smtpc.pp;
|
||||
const char *eob;
|
||||
ssize_t len;
|
||||
@@ -1534,7 +1583,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
||||
|
||||
if(conn->data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
struct SMTP *smtp = conn->data->state.proto.smtp;
|
||||
struct SMTP *smtp = conn->data->req.protop;
|
||||
smtp->transfer = FTPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
@@ -1571,15 +1620,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE; /* default to false */
|
||||
|
||||
/* Since connections can be re-used between SessionHandles, there might be a
|
||||
connection already existing but on a fresh SessionHandle struct. As such
|
||||
we make sure we have a good SMTP struct to play with. For new connections
|
||||
the SMTP struct is allocated and setup in the smtp_connect() function. */
|
||||
Curl_reset_reqproto(conn);
|
||||
result = smtp_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = smtp_regular_transfer(conn, done);
|
||||
|
||||
return result;
|
||||
@@ -1622,7 +1662,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn,
|
||||
/* Call this when the DO phase has completed */
|
||||
static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
|
||||
{
|
||||
struct SMTP *smtp = conn->data->state.proto.smtp;
|
||||
struct SMTP *smtp = conn->data->req.protop;
|
||||
|
||||
(void)connected;
|
||||
|
||||
@@ -1687,6 +1727,7 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
|
||||
static CURLcode smtp_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result;
|
||||
|
||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||
/* Unless we have asked to tunnel SMTP operations through the proxy, we
|
||||
@@ -1702,17 +1743,20 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
/* set it up as a HTTP connection instead */
|
||||
return conn->handler->setup_connection(conn);
|
||||
|
||||
/* We explicitly mark this connection as persistent here as we're doing
|
||||
SMTP over HTTP and thus we accidentally avoid setting this value
|
||||
otherwise */
|
||||
conn->bits.close = FALSE;
|
||||
#else
|
||||
failf(data, "SMTP over http proxy requires HTTP support built-in!");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialise the SMTP layer */
|
||||
result = smtp_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
data->state.path++; /* don't include the initial slash */
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -1742,18 +1786,20 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
|
||||
|
||||
if(strequal(value, "*"))
|
||||
smtpc->prefmech = SASL_AUTH_ANY;
|
||||
else if(strequal(value, "LOGIN"))
|
||||
else if(strequal(value, SASL_MECH_STRING_LOGIN))
|
||||
smtpc->prefmech = SASL_MECH_LOGIN;
|
||||
else if(strequal(value, "PLAIN"))
|
||||
else if(strequal(value, SASL_MECH_STRING_PLAIN))
|
||||
smtpc->prefmech = SASL_MECH_PLAIN;
|
||||
else if(strequal(value, "CRAM-MD5"))
|
||||
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5))
|
||||
smtpc->prefmech = SASL_MECH_CRAM_MD5;
|
||||
else if(strequal(value, "DIGEST-MD5"))
|
||||
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5))
|
||||
smtpc->prefmech = SASL_MECH_DIGEST_MD5;
|
||||
else if(strequal(value, "GSSAPI"))
|
||||
else if(strequal(value, SASL_MECH_STRING_GSSAPI))
|
||||
smtpc->prefmech = SASL_MECH_GSSAPI;
|
||||
else if(strequal(value, "NTLM"))
|
||||
else if(strequal(value, SASL_MECH_STRING_NTLM))
|
||||
smtpc->prefmech = SASL_MECH_NTLM;
|
||||
else if(strequal(value, SASL_MECH_STRING_XOAUTH2))
|
||||
smtpc->prefmech = SASL_MECH_XOAUTH2;
|
||||
else
|
||||
smtpc->prefmech = SASL_AUTH_NONE;
|
||||
}
|
||||
@@ -1801,7 +1847,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
||||
ssize_t i;
|
||||
ssize_t si;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->state.proto.smtp;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
/* Do we need to allocate the scatch buffer? */
|
||||
if(!data->state.scratch) {
|
||||
|
@@ -44,6 +44,7 @@ typedef enum {
|
||||
SMTP_AUTH_DIGESTMD5_RESP,
|
||||
SMTP_AUTH_NTLM,
|
||||
SMTP_AUTH_NTLM_TYPE2MSG,
|
||||
SMTP_AUTH_XOAUTH2,
|
||||
SMTP_AUTH_FINAL,
|
||||
SMTP_MAIL, /* MAIL FROM */
|
||||
SMTP_RCPT, /* RCPT TO */
|
||||
|
63
lib/ssh.c
63
lib/ssh.c
@@ -149,13 +149,15 @@ static int ssh_perform_getsock(const struct connectdata *conn,
|
||||
number of sockets */
|
||||
int numsocks);
|
||||
|
||||
static CURLcode ssh_setup_connection(struct connectdata *conn);
|
||||
|
||||
/*
|
||||
* SCP protocol handler.
|
||||
*/
|
||||
|
||||
const struct Curl_handler Curl_handler_scp = {
|
||||
"SCP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
ssh_setup_connection, /* setup_connection */
|
||||
ssh_do, /* do_it */
|
||||
scp_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -181,7 +183,7 @@ const struct Curl_handler Curl_handler_scp = {
|
||||
|
||||
const struct Curl_handler Curl_handler_sftp = {
|
||||
"SFTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
ssh_setup_connection, /* setup_connection */
|
||||
ssh_do, /* do_it */
|
||||
sftp_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
@@ -200,7 +202,6 @@ const struct Curl_handler Curl_handler_sftp = {
|
||||
| PROTOPT_NOURLQUERY /* flags */
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
kbd_callback(const char *name, int name_len, const char *instruction,
|
||||
int instruction_len, int num_prompts,
|
||||
@@ -687,7 +688,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SSHPROTO *sftp_scp = data->state.proto.ssh;
|
||||
struct SSHPROTO *sftp_scp = data->req.protop;
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
char *new_readdir_line;
|
||||
@@ -2287,6 +2288,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
sshc->actualcode = result;
|
||||
}
|
||||
else {
|
||||
/* store this original bitmask setup to use later on if we can't
|
||||
figure out a "real" bitmask */
|
||||
sshc->orig_waitfor = data->req.keepon;
|
||||
|
||||
/* we want to use the _sending_ function even when the socket turns
|
||||
out readable as the underlying libssh2 scp send function will deal
|
||||
with both accordingly */
|
||||
@@ -2603,9 +2608,7 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
|
||||
{
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
int dir;
|
||||
if(!block)
|
||||
conn->waitfor = 0;
|
||||
else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
|
||||
if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
|
||||
/* translate the libssh2 define bits into our own bit defines */
|
||||
conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
|
||||
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
|
||||
@@ -2689,25 +2692,14 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
|
||||
/*
|
||||
* SSH setup and connection
|
||||
*/
|
||||
static CURLcode ssh_init(struct connectdata *conn)
|
||||
static CURLcode ssh_setup_connection(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SSHPROTO *ssh;
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
|
||||
sshc->actualcode = CURLE_OK; /* reset error code */
|
||||
sshc->secondCreateDirs =0; /* reset the create dir attempt state
|
||||
variable */
|
||||
|
||||
if(data->state.proto.ssh)
|
||||
return CURLE_OK;
|
||||
|
||||
ssh = calloc(1, sizeof(struct SSHPROTO));
|
||||
conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
|
||||
if(!ssh)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
data->state.proto.ssh = ssh;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -2731,14 +2723,6 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
|
||||
function to make the re-use checks properly be able to check this bit. */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
result = ssh_init(conn);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->handler->protocol & CURLPROTO_SCP) {
|
||||
conn->recv[FIRSTSOCKET] = scp_recv;
|
||||
conn->send[FIRSTSOCKET] = scp_send;
|
||||
@@ -2856,23 +2840,16 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
|
||||
CURLcode res;
|
||||
bool connected = 0;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
|
||||
*done = FALSE; /* default to false */
|
||||
|
||||
/*
|
||||
Since connections can be re-used between SessionHandles, this might be a
|
||||
connection already existing but on a fresh SessionHandle struct so we must
|
||||
make sure we have a good 'struct SSHPROTO' to play with. For new
|
||||
connections, the struct SSHPROTO is allocated and setup in the
|
||||
ssh_connect() function.
|
||||
*/
|
||||
Curl_reset_reqproto(conn);
|
||||
res = ssh_init(conn);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
data->req.size = -1; /* make sure this is unknown at this point */
|
||||
|
||||
sshc->actualcode = CURLE_OK; /* reset error code */
|
||||
sshc->secondCreateDirs =0; /* reset the create dir attempt state
|
||||
variable */
|
||||
|
||||
Curl_pgrsSetUploadCounter(data, 0);
|
||||
Curl_pgrsSetDownloadCounter(data, 0);
|
||||
Curl_pgrsSetUploadSize(data, 0);
|
||||
@@ -2895,7 +2872,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
struct ssh_conn *ssh = &conn->proto.sshc;
|
||||
(void) dead_connection;
|
||||
|
||||
Curl_safefree(conn->data->state.proto.ssh);
|
||||
Curl_safefree(conn->data->req.protop);
|
||||
|
||||
if(ssh->ssh_session) {
|
||||
/* only if there's a session still around to use! */
|
||||
@@ -2913,7 +2890,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh;
|
||||
struct SSHPROTO *sftp_scp = conn->data->req.protop;
|
||||
|
||||
if(status == CURLE_OK) {
|
||||
/* run the state-machine
|
||||
@@ -3060,7 +3037,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
|
||||
DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
|
||||
|
||||
Curl_safefree(conn->data->state.proto.ssh);
|
||||
Curl_safefree(conn->data->req.protop);
|
||||
|
||||
if(conn->proto.sshc.ssh_session) {
|
||||
/* only if there's a session still around to use! */
|
||||
|
63
lib/ssluse.c
63
lib/ssluse.c
@@ -294,6 +294,49 @@ static int do_file_type(const char *type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS)
|
||||
/*
|
||||
* Supply default password to the engine user interface conversation.
|
||||
* The password is passed by OpenSSL engine from ENGINE_load_private_key()
|
||||
* last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
|
||||
*/
|
||||
static int ssl_ui_reader(UI *ui, UI_STRING *uis)
|
||||
{
|
||||
const char *password;
|
||||
switch(UI_get_string_type(uis)) {
|
||||
case UIT_PROMPT:
|
||||
case UIT_VERIFY:
|
||||
password = (const char*)UI_get0_user_data(ui);
|
||||
if(NULL != password &&
|
||||
UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
|
||||
UI_set_result(ui, uis, password);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suppress interactive request for a default password if available.
|
||||
*/
|
||||
static int ssl_ui_writer(UI *ui, UI_STRING *uis)
|
||||
{
|
||||
switch(UI_get_string_type(uis)) {
|
||||
case UIT_PROMPT:
|
||||
case UIT_VERIFY:
|
||||
if(NULL != UI_get0_user_data(ui) &&
|
||||
UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
int cert_stuff(struct connectdata *conn,
|
||||
SSL_CTX* ctx,
|
||||
@@ -527,7 +570,16 @@ int cert_stuff(struct connectdata *conn,
|
||||
EVP_PKEY *priv_key = NULL;
|
||||
if(data->state.engine) {
|
||||
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||
UI_METHOD *ui_method = UI_OpenSSL();
|
||||
UI_METHOD *ui_method =
|
||||
UI_create_method((char *)"cURL user interface");
|
||||
if(NULL == ui_method) {
|
||||
failf(data, "unable do create OpenSSL user-interface method");
|
||||
return 0;
|
||||
}
|
||||
UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
|
||||
UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
|
||||
UI_method_set_reader(ui_method, ssl_ui_reader);
|
||||
UI_method_set_writer(ui_method, ssl_ui_writer);
|
||||
#endif
|
||||
/* the typecast below was added to please mingw32 */
|
||||
priv_key = (EVP_PKEY *)
|
||||
@@ -536,6 +588,9 @@ int cert_stuff(struct connectdata *conn,
|
||||
ui_method,
|
||||
#endif
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||
UI_destroy_method(ui_method);
|
||||
#endif
|
||||
if(!priv_key) {
|
||||
failf(data, "failed to load private key from crypto engine");
|
||||
return 0;
|
||||
@@ -1137,6 +1192,8 @@ static CURLcode verifyhost(struct connectdata *conn,
|
||||
/* an alternative name field existed, but didn't match and then
|
||||
we MUST fail */
|
||||
infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
|
||||
failf(data, "SSL: no alternative certificate subject name matches "
|
||||
"target host name '%s'", conn->host.dispname);
|
||||
res = CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else {
|
||||
@@ -1755,7 +1812,7 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
*/
|
||||
if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
|
||||
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
|
||||
conn->host.name, conn->port);
|
||||
conn->host.name, conn->remote_port);
|
||||
return rc;
|
||||
}
|
||||
/* Could be a CERT problem */
|
||||
@@ -2296,7 +2353,7 @@ ossl_connect_step3(struct connectdata *conn,
|
||||
* operations.
|
||||
*/
|
||||
|
||||
if(!data->set.ssl.verifypeer)
|
||||
if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost)
|
||||
(void)servercert(conn, connssl, FALSE);
|
||||
else
|
||||
retcode = servercert(conn, connssl, TRUE);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2004 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2004 - 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
|
||||
@@ -361,6 +361,9 @@ curl_multi_strerror(CURLMcode error)
|
||||
case CURLM_UNKNOWN_OPTION:
|
||||
return "Unknown option";
|
||||
|
||||
case CURLM_ADDED_ALREADY:
|
||||
return "The easy handle is already added to a multi handle";
|
||||
|
||||
case CURLM_LAST:
|
||||
break;
|
||||
}
|
||||
|
32
lib/telnet.c
32
lib/telnet.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
|
||||
@@ -247,7 +247,7 @@ CURLcode init_telnet(struct connectdata *conn)
|
||||
if(!tn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
conn->data->state.proto.telnet = (void *)tn; /* make us known */
|
||||
conn->data->req.protop = tn; /* make us known */
|
||||
|
||||
tn->telrcv_state = CURL_TS_DATA;
|
||||
|
||||
@@ -292,7 +292,7 @@ CURLcode init_telnet(struct connectdata *conn)
|
||||
static void negotiate(struct connectdata *conn)
|
||||
{
|
||||
int i;
|
||||
struct TELNET *tn = (struct TELNET *) conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
|
||||
|
||||
for(i = 0;i < CURL_NTELOPTS;i++) {
|
||||
if(i==CURL_TELOPT_ECHO)
|
||||
@@ -366,7 +366,7 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
|
||||
static
|
||||
void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
if(newstate == CURL_YES) {
|
||||
switch(tn->him[option]) {
|
||||
case CURL_NO:
|
||||
@@ -440,7 +440,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
static
|
||||
void rec_will(struct connectdata *conn, int option)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
switch(tn->him[option]) {
|
||||
case CURL_NO:
|
||||
if(tn->him_preferred[option] == CURL_YES) {
|
||||
@@ -488,7 +488,7 @@ void rec_will(struct connectdata *conn, int option)
|
||||
static
|
||||
void rec_wont(struct connectdata *conn, int option)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
switch(tn->him[option]) {
|
||||
case CURL_NO:
|
||||
/* Already disabled */
|
||||
@@ -530,7 +530,7 @@ void rec_wont(struct connectdata *conn, int option)
|
||||
static void
|
||||
set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
if(newstate == CURL_YES) {
|
||||
switch(tn->us[option]) {
|
||||
case CURL_NO:
|
||||
@@ -604,7 +604,7 @@ set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
static
|
||||
void rec_do(struct connectdata *conn, int option)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
switch(tn->us[option]) {
|
||||
case CURL_NO:
|
||||
if(tn->us_preferred[option] == CURL_YES) {
|
||||
@@ -664,7 +664,7 @@ void rec_do(struct connectdata *conn, int option)
|
||||
static
|
||||
void rec_dont(struct connectdata *conn, int option)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
switch(tn->us[option]) {
|
||||
case CURL_NO:
|
||||
/* Already disabled */
|
||||
@@ -825,7 +825,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
|
||||
char option_keyword[128];
|
||||
char option_arg[256];
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
CURLcode result = CURLE_OK;
|
||||
int binary_option;
|
||||
|
||||
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
|
||||
char varname[128];
|
||||
char varval[128];
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)data->req.protop;
|
||||
|
||||
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
|
||||
switch (CURL_SB_GET(tn)) {
|
||||
@@ -1009,7 +1009,7 @@ static void sendsuboption(struct connectdata *conn, int option)
|
||||
unsigned char*uc1, *uc2;
|
||||
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)data->req.protop;
|
||||
|
||||
switch (option) {
|
||||
case CURL_TELOPT_NAWS:
|
||||
@@ -1067,7 +1067,7 @@ CURLcode telrcv(struct connectdata *conn,
|
||||
int in = 0;
|
||||
int startwrite=-1;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)data->req.protop;
|
||||
|
||||
#define startskipping() \
|
||||
if(startwrite >= 0) { \
|
||||
@@ -1264,7 +1264,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
|
||||
static CURLcode telnet_done(struct connectdata *conn,
|
||||
CURLcode status, bool premature)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
|
||||
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
|
||||
(void)status; /* unused */
|
||||
(void)premature; /* not used */
|
||||
|
||||
@@ -1274,7 +1274,7 @@ static CURLcode telnet_done(struct connectdata *conn,
|
||||
curl_slist_free_all(tn->telnet_vars);
|
||||
tn->telnet_vars = NULL;
|
||||
|
||||
Curl_safefree(conn->data->state.proto.telnet);
|
||||
Curl_safefree(conn->data->req.protop);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -1318,7 +1318,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
if(code)
|
||||
return code;
|
||||
|
||||
tn = (struct TELNET *)data->state.proto.telnet;
|
||||
tn = (struct TELNET *)data->req.protop;
|
||||
|
||||
code = check_telnet_options(conn);
|
||||
if(code)
|
||||
|
22
lib/tftp.c
22
lib/tftp.c
@@ -56,6 +56,7 @@
|
||||
#include "multiif.h"
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
#include "speedcheck.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -947,10 +948,6 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
|
||||
blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
|
||||
if(!state)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@@ -1259,6 +1256,15 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
||||
}
|
||||
else {
|
||||
/* The multi code doesn't have this logic for the DOING state so we
|
||||
provide it for TFTP since it may do the entire transfer in this
|
||||
state. */
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else
|
||||
result = Curl_speedcheck(conn->data, Curl_tvnow());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1307,14 +1313,6 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*done = FALSE;
|
||||
|
||||
/*
|
||||
Since connections can be re-used between SessionHandles, this might be a
|
||||
connection already existing but on a fresh SessionHandle struct so we must
|
||||
make sure we have a good 'struct TFTP' to play with. For new connections,
|
||||
the struct TFTP is allocated and setup in the tftp_connect() function.
|
||||
*/
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
if(!conn->proto.tftpc) {
|
||||
code = tftp_connect(conn, done);
|
||||
if(code)
|
||||
|
@@ -101,8 +101,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
bool sending_http_headers = FALSE;
|
||||
|
||||
if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) &&
|
||||
(data->state.proto.http->sending == HTTPSEND_REQUEST)) {
|
||||
if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) {
|
||||
const struct HTTP *http = data->req.protop;
|
||||
|
||||
if(http->sending == HTTPSEND_REQUEST)
|
||||
/* We're sending the HTTP request headers, not the data.
|
||||
Remember that so we don't re-translate them into garbage. */
|
||||
sending_http_headers = TRUE;
|
||||
@@ -540,6 +542,10 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
|
||||
if(!Curl_meets_timecondition(data, k->timeofdoc)) {
|
||||
*done = TRUE;
|
||||
/* We're simulating a http 304 from server so we return
|
||||
what should have been returned from the server */
|
||||
data->info.httpcode = 304;
|
||||
infof(data, "Simulate a HTTP 304 response!\n");
|
||||
/* we abort the transfer before it is completed == we ruin the
|
||||
re-use ability. Close the connection */
|
||||
conn->bits.close = TRUE;
|
||||
@@ -810,9 +816,10 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
|
||||
/* HTTP pollution, this should be written nicer to become more
|
||||
protocol agnostic. */
|
||||
int fillcount;
|
||||
struct HTTP *http = data->req.protop;
|
||||
|
||||
if((k->exp100 == EXP100_SENDING_REQUEST) &&
|
||||
(data->state.proto.http->sending == HTTPSEND_BODY)) {
|
||||
(http->sending == HTTPSEND_BODY)) {
|
||||
/* If this call is to send body data, we must take some action:
|
||||
We have sent off the full HTTP 1.1 request, and we shall now
|
||||
go into the Expect: 100 state and await such a header */
|
||||
@@ -827,7 +834,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) {
|
||||
if(data->state.proto.http->sending == HTTPSEND_REQUEST)
|
||||
if(http->sending == HTTPSEND_REQUEST)
|
||||
/* We're sending the HTTP request headers, not the data.
|
||||
Remember that so we don't change the line endings. */
|
||||
sending_http_headers = TRUE;
|
||||
@@ -1870,10 +1877,12 @@ CURLcode Curl_retry_request(struct connectdata *conn,
|
||||
transferred! */
|
||||
|
||||
|
||||
if((conn->handler->protocol&CURLPROTO_HTTP) &&
|
||||
data->state.proto.http->writebytecount)
|
||||
if(conn->handler->protocol&CURLPROTO_HTTP) {
|
||||
struct HTTP *http = data->req.protop;
|
||||
if(http->writebytecount)
|
||||
return Curl_readrewind(conn);
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -1930,6 +1939,7 @@ Curl_setup_transfer(
|
||||
k->keepon |= KEEP_RECV;
|
||||
|
||||
if(conn->writesockfd != CURL_SOCKET_BAD) {
|
||||
struct HTTP *http = data->req.protop;
|
||||
/* HTTP 1.1 magic:
|
||||
|
||||
Even if we require a 100-return code before uploading data, we might
|
||||
@@ -1940,13 +1950,16 @@ Curl_setup_transfer(
|
||||
state info where we wait for the 100-return code
|
||||
*/
|
||||
if((data->state.expect100header) &&
|
||||
(data->state.proto.http->sending == HTTPSEND_BODY)) {
|
||||
(conn->handler->protocol&CURLPROTO_HTTP) &&
|
||||
(http->sending == HTTPSEND_BODY)) {
|
||||
/* wait with write until we either got 100-continue or a timeout */
|
||||
k->exp100 = EXP100_AWAITING_CONTINUE;
|
||||
k->start100 = Curl_tvnow();
|
||||
|
||||
/* set a timeout for the multi interface */
|
||||
Curl_expire(data, CURL_TIMEOUT_EXPECT_100);
|
||||
/* Set a timeout for the multi interface. Add the inaccuracy margin so
|
||||
that we don't fire slightly too early and get denied to run. */
|
||||
Curl_expire(data, CURL_TIMEOUT_EXPECT_100 +
|
||||
MULTI_TIMEOUT_INACCURACY / 1000);
|
||||
}
|
||||
else {
|
||||
if(data->state.expect100header)
|
||||
|
324
lib/url.c
324
lib/url.c
@@ -144,7 +144,8 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
|
||||
static CURLcode do_init(struct connectdata *conn);
|
||||
static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
struct connectdata *conn,
|
||||
char *user, char *passwd, char *options);
|
||||
char **userptr, char **passwdptr,
|
||||
char **optionsptr);
|
||||
static CURLcode parse_login_details(const char *login, const size_t len,
|
||||
char **userptr, char **passwdptr,
|
||||
char **optionsptr);
|
||||
@@ -417,7 +418,8 @@ CURLcode Curl_close(struct SessionHandle *data)
|
||||
Curl_safefree(data->state.pathbuffer);
|
||||
data->state.path = NULL;
|
||||
|
||||
Curl_safefree(data->state.proto.generic);
|
||||
/* freed here just in case DONE wasn't called */
|
||||
Curl_free_request_state(data);
|
||||
|
||||
/* Close down all open SSL info and sessions */
|
||||
Curl_ssl_close_all(data);
|
||||
@@ -611,7 +613,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
||||
res = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
Curl_easy_initHandleData(data);
|
||||
res = Curl_init_userdefined(&data->set);
|
||||
|
||||
data->state.headersize=HEADERSIZE;
|
||||
@@ -1202,7 +1203,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
* This sets a requested HTTP version to be used. The value is one of
|
||||
* the listed enums in curl/curl.h.
|
||||
*/
|
||||
data->set.httpversion = va_arg(param, long);
|
||||
arg = va_arg(param, long);
|
||||
#ifndef USE_NGHTTP2
|
||||
if(arg == CURL_HTTP_VERSION_2_0)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
#endif
|
||||
data->set.httpversion = arg;
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPAUTH:
|
||||
@@ -1568,6 +1574,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
result = setstropt(&data->set.str[STRING_PASSWORD],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_XOAUTH2_BEARER:
|
||||
/*
|
||||
* XOAUTH2 bearer token to use in the operation
|
||||
*/
|
||||
result = setstropt(&data->set.str[STRING_BEARER],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_POSTQUOTE:
|
||||
/*
|
||||
* List of RAW FTP commands to use after a transfer
|
||||
@@ -2442,6 +2455,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
case CURLOPT_DNS_SERVERS:
|
||||
result = Curl_set_dns_servers(data, va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_DNS_INTERFACE:
|
||||
result = Curl_set_dns_interface(data, va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_DNS_LOCAL_IP4:
|
||||
result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_DNS_LOCAL_IP6:
|
||||
result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
|
||||
break;
|
||||
|
||||
case CURLOPT_TCP_KEEPALIVE:
|
||||
data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||
@@ -2487,6 +2509,7 @@ static void conn_free(struct connectdata *conn)
|
||||
|
||||
Curl_safefree(conn->user);
|
||||
Curl_safefree(conn->passwd);
|
||||
Curl_safefree(conn->xoauth2_bearer);
|
||||
Curl_safefree(conn->options);
|
||||
Curl_safefree(conn->proxyuser);
|
||||
Curl_safefree(conn->proxypasswd);
|
||||
@@ -3606,7 +3629,7 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
||||
if(!conn->send_pipe || !conn->recv_pipe)
|
||||
goto error;
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CLEAR;
|
||||
#endif
|
||||
|
||||
@@ -3687,7 +3710,8 @@ static CURLcode findprotocol(struct SessionHandle *data,
|
||||
static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
struct connectdata *conn,
|
||||
bool *prot_missing,
|
||||
char *user, char *passwd, char *options)
|
||||
char **userp, char **passwdp,
|
||||
char **optionsp)
|
||||
{
|
||||
char *at;
|
||||
char *fragment;
|
||||
@@ -3931,7 +3955,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||
* Parse the login details from the URL and strip them out of
|
||||
* the host name
|
||||
*/
|
||||
result = parse_url_login(data, conn, user, passwd, options);
|
||||
result = parse_url_login(data, conn, userp, passwdp, optionsp);
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
|
||||
@@ -4016,18 +4040,31 @@ static CURLcode setup_range(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* Setup connection internals specific to the requested protocol.
|
||||
/*
|
||||
* setup_connection_internals() -
|
||||
*
|
||||
* Setup connection internals specific to the requested protocol in the
|
||||
* SessionHandle. This is inited and setup before the connection is made but
|
||||
* is about the particular protocol that is to be used.
|
||||
*
|
||||
* This MUST get called after proxy magic has been figured out.
|
||||
***************************************************************/
|
||||
*/
|
||||
static CURLcode setup_connection_internals(struct connectdata *conn)
|
||||
{
|
||||
const struct Curl_handler * p;
|
||||
CURLcode result;
|
||||
|
||||
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
|
||||
/* in some case in the multi state-machine, we go back to the CONNECT state
|
||||
and then a second (or third or...) call to this function will be made
|
||||
without doing a DISCONNECT or DONE in between (since the connection is
|
||||
yet in place) and therefore this function needs to first make sure
|
||||
there's no lingering previous data allocated. */
|
||||
Curl_free_request_state(conn->data);
|
||||
|
||||
/* Scan protocol handler table. */
|
||||
memset(&conn->data->req, 0, sizeof(struct SingleRequest));
|
||||
conn->data->req.maxdownload = -1;
|
||||
|
||||
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
|
||||
|
||||
/* Perform setup complement if some. */
|
||||
p = conn->handler;
|
||||
@@ -4045,11 +4082,26 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
|
||||
/* we check for -1 here since if proxy was detected already, this
|
||||
was very likely already set to the proxy port */
|
||||
conn->port = p->defport;
|
||||
|
||||
/* only if remote_port was not already parsed off the URL we use the
|
||||
default port number */
|
||||
if(!conn->remote_port)
|
||||
conn->remote_port = (unsigned short)conn->given->defport;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_free_request_state() should free temp data that was allocated in the
|
||||
* SessionHandle for this single request.
|
||||
*/
|
||||
|
||||
void Curl_free_request_state(struct SessionHandle *data)
|
||||
{
|
||||
Curl_safefree(data->req.protop);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/****************************************************************
|
||||
* Checks if the host is in the noproxy list. returns true if it matches
|
||||
@@ -4411,7 +4463,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
|
||||
*/
|
||||
static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
struct connectdata *conn,
|
||||
char *user, char *passwd, char *options)
|
||||
char **user, char **passwd, char **options)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *userp = NULL;
|
||||
@@ -4428,16 +4480,16 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
char *ptr = strchr(conn->host.name, '@');
|
||||
char *login = conn->host.name;
|
||||
|
||||
user[0] = 0; /* to make everything well-defined */
|
||||
passwd[0] = 0;
|
||||
options[0] = 0;
|
||||
DEBUGASSERT(!**user);
|
||||
DEBUGASSERT(!**passwd);
|
||||
DEBUGASSERT(!**options);
|
||||
|
||||
if(!ptr)
|
||||
goto out;
|
||||
|
||||
/* We will now try to extract the
|
||||
* possible login information in a string like:
|
||||
* ftp://user:password@ftp.my.site:8021/README */
|
||||
if(ptr) {
|
||||
/* There's login information to the left of the @ */
|
||||
|
||||
conn->host.name = ++ptr;
|
||||
|
||||
/* So the hostname is sane. Only bother interpreting the
|
||||
@@ -4446,11 +4498,15 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
* set user/passwd, but doing that first adds more cases here :-(
|
||||
*/
|
||||
|
||||
if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
|
||||
if(data->set.use_netrc == CURL_NETRC_REQUIRED)
|
||||
goto out;
|
||||
|
||||
/* We could use the login information in the URL so extract it */
|
||||
result = parse_login_details(login, ptr - login - 1,
|
||||
&userp, &passwdp, &optionsp);
|
||||
if(!result) {
|
||||
if(result != CURLE_OK)
|
||||
goto out;
|
||||
|
||||
if(userp) {
|
||||
char *newname;
|
||||
|
||||
@@ -4461,56 +4517,44 @@ static CURLcode parse_url_login(struct SessionHandle *data,
|
||||
/* Decode the user */
|
||||
newname = curl_easy_unescape(data, userp, 0, NULL);
|
||||
if(!newname) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strlen(newname) < MAX_CURL_USER_LENGTH)
|
||||
strcpy(user, newname);
|
||||
|
||||
free(newname);
|
||||
free(*user);
|
||||
*user = newname;
|
||||
}
|
||||
|
||||
if(passwdp) {
|
||||
/* We have a password in the URL so decode it */
|
||||
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
|
||||
if(!newpasswd) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
|
||||
strcpy(passwd, newpasswd);
|
||||
|
||||
free(newpasswd);
|
||||
free(*passwd);
|
||||
*passwd = newpasswd;
|
||||
}
|
||||
|
||||
if(optionsp) {
|
||||
/* We have an options list in the URL so decode it */
|
||||
char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
|
||||
if(!newoptions) {
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
|
||||
strcpy(options, newoptions);
|
||||
free(*options);
|
||||
*options = newoptions;
|
||||
}
|
||||
|
||||
free(newoptions);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
Curl_safefree(userp);
|
||||
Curl_safefree(passwdp);
|
||||
Curl_safefree(optionsp);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -4765,29 +4809,35 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
|
||||
* Override the login details from the URL with that in the CURLOPT_USERPWD
|
||||
* option or a .netrc file, if applicable.
|
||||
*/
|
||||
static void override_login(struct SessionHandle *data,
|
||||
static CURLcode override_login(struct SessionHandle *data,
|
||||
struct connectdata *conn,
|
||||
char *user, char *passwd, char *options)
|
||||
char **userp, char **passwdp, char **optionsp)
|
||||
{
|
||||
if(data->set.str[STRING_USERNAME]) {
|
||||
strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
|
||||
user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||
free(*userp);
|
||||
*userp = strdup(data->set.str[STRING_USERNAME]);
|
||||
if(!*userp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_PASSWORD]) {
|
||||
strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
|
||||
passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||
free(*passwdp);
|
||||
*passwdp = strdup(data->set.str[STRING_PASSWORD]);
|
||||
if(!*passwdp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_OPTIONS]) {
|
||||
strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH);
|
||||
options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||
free(*optionsp);
|
||||
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
|
||||
if(!*optionsp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
conn->bits.netrc = FALSE;
|
||||
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
|
||||
if(Curl_parsenetrc(conn->host.name,
|
||||
user, passwd,
|
||||
userp, passwdp,
|
||||
data->set.str[STRING_NETRC_FILE])) {
|
||||
infof(data, "Couldn't find host %s in the "
|
||||
DOT_CHAR "netrc file; using defaults\n",
|
||||
@@ -4802,6 +4852,8 @@ static void override_login(struct SessionHandle *data,
|
||||
conn->bits.user_passwd = TRUE; /* enable user+password */
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5018,9 +5070,9 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
struct connectdata *conn;
|
||||
struct connectdata *conn_temp = NULL;
|
||||
size_t urllen;
|
||||
char user[MAX_CURL_USER_LENGTH];
|
||||
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
||||
char options[MAX_CURL_OPTIONS_LENGTH];
|
||||
char *user = NULL;
|
||||
char *passwd = NULL;
|
||||
char *options = NULL;
|
||||
bool reuse;
|
||||
char *proxy = NULL;
|
||||
bool prot_missing = FALSE;
|
||||
@@ -5035,8 +5087,10 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
* Check input data
|
||||
*************************************************************/
|
||||
|
||||
if(!data->change.url)
|
||||
return CURLE_URL_MALFORMAT;
|
||||
if(!data->change.url) {
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* First, split up the current URL in parts so that we can use the
|
||||
parts for checking against the already present connections. In order
|
||||
@@ -5044,8 +5098,10 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
connection data struct and fill in for comparison purposes. */
|
||||
conn = allocate_conn(data);
|
||||
|
||||
if(!conn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!conn) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We must set the return variable as soon as possible, so that our
|
||||
parent can cleanup any possible allocs we may have done before
|
||||
@@ -5075,24 +5131,35 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
data->state.path = NULL;
|
||||
|
||||
data->state.pathbuffer = malloc(urllen+2);
|
||||
if(NULL == data->state.pathbuffer)
|
||||
return CURLE_OUT_OF_MEMORY; /* really bad error */
|
||||
if(NULL == data->state.pathbuffer) {
|
||||
result = CURLE_OUT_OF_MEMORY; /* really bad error */
|
||||
goto out;
|
||||
}
|
||||
data->state.path = data->state.pathbuffer;
|
||||
|
||||
conn->host.rawalloc = malloc(urllen+2);
|
||||
if(NULL == conn->host.rawalloc) {
|
||||
Curl_safefree(data->state.pathbuffer);
|
||||
data->state.path = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
conn->host.name = conn->host.rawalloc;
|
||||
conn->host.name[0] = 0;
|
||||
|
||||
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd,
|
||||
options);
|
||||
user = strdup("");
|
||||
passwd = strdup("");
|
||||
options = strdup("");
|
||||
if(!user || !passwd || !options) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
|
||||
&options);
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
/*************************************************************
|
||||
* No protocol part in URL was used, add it!
|
||||
@@ -5106,8 +5173,8 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
|
||||
|
||||
if(!reurl) {
|
||||
Curl_safefree(proxy);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(data->change.url_alloc) {
|
||||
@@ -5137,6 +5204,13 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_BEARER]) {
|
||||
conn->xoauth2_bearer = strdup(data->set.str[STRING_BEARER]);
|
||||
if(!conn->xoauth2_bearer) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/*************************************************************
|
||||
* Extract the user and password from the authentication string
|
||||
@@ -5144,7 +5218,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
if(conn->bits.proxy_user_passwd) {
|
||||
result = parse_proxy_auth(data, conn);
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
@@ -5155,7 +5229,8 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
/* if global proxy is set, this is it */
|
||||
if(NULL == proxy) {
|
||||
failf(data, "memory shortage");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5183,16 +5258,17 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
if(proxy) {
|
||||
result = parse_proxy(data, conn, proxy);
|
||||
|
||||
free(proxy); /* parse_proxy copies the proxy string */
|
||||
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
if((conn->proxytype == CURLPROXY_HTTP) ||
|
||||
(conn->proxytype == CURLPROXY_HTTP_1_0)) {
|
||||
#ifdef CURL_DISABLE_HTTP
|
||||
/* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
result = CURLE_UNSUPPORTED_PROTOCOL;
|
||||
goto out;
|
||||
#else
|
||||
/* force this connection's protocol to become HTTP if not already
|
||||
compatible - if it isn't tunneling through */
|
||||
@@ -5217,15 +5293,36 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
/*************************************************************
|
||||
* If the protocol is using SSL and HTTP proxy is used, we set
|
||||
* the tunnel_proxy bit.
|
||||
*************************************************************/
|
||||
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
|
||||
conn->bits.tunnel_proxy = TRUE;
|
||||
|
||||
/*************************************************************
|
||||
* Figure out the remote port number and fix it in the URL
|
||||
*************************************************************/
|
||||
result = parse_remote_port(data, conn);
|
||||
if(result != CURLE_OK)
|
||||
goto out;
|
||||
|
||||
/* Check for overridden login details and set them accordingly so they
|
||||
they are known when protocol->setup_connection is called! */
|
||||
result = override_login(data, conn, &user, &passwd, &options);
|
||||
if(result != CURLE_OK)
|
||||
goto out;
|
||||
result = set_login(conn, user, passwd, options);
|
||||
if(result != CURLE_OK)
|
||||
goto out;
|
||||
|
||||
/*************************************************************
|
||||
* Setup internals depending on protocol. Needs to be done after
|
||||
* we figured out what/if proxy to use.
|
||||
*************************************************************/
|
||||
result = setup_connection_internals(conn);
|
||||
if(result != CURLE_OK) {
|
||||
Curl_safefree(proxy);
|
||||
return result;
|
||||
}
|
||||
if(result != CURLE_OK)
|
||||
goto out;
|
||||
|
||||
conn->recv[FIRSTSOCKET] = Curl_recv_plain;
|
||||
conn->send[FIRSTSOCKET] = Curl_send_plain;
|
||||
@@ -5258,7 +5355,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
DEBUGASSERT(conn->handler->done);
|
||||
/* we ignore the return code for the protocol-specific DONE */
|
||||
(void)conn->handler->done(conn, result, FALSE);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
|
||||
@@ -5266,32 +5363,12 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
/* since we skip do_init() */
|
||||
Curl_speedinit(data);
|
||||
do_init(conn);
|
||||
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
* If the protocol is using SSL and HTTP proxy is used, we set
|
||||
* the tunnel_proxy bit.
|
||||
*************************************************************/
|
||||
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
|
||||
conn->bits.tunnel_proxy = TRUE;
|
||||
|
||||
/*************************************************************
|
||||
* Figure out the remote port number and fix it in the URL
|
||||
*************************************************************/
|
||||
result = parse_remote_port(data, conn);
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
|
||||
/* Check for overridden login details and set them accordingly */
|
||||
override_login(data, conn, user, passwd, options);
|
||||
result = set_login(conn, user, passwd, options);
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
|
||||
/* Get a cloned copy of the SSL config situation stored in the
|
||||
connection struct. But to get this going nicely, we must first make
|
||||
sure that the strings in the master copy are pointing to the correct
|
||||
@@ -5313,8 +5390,10 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#endif
|
||||
|
||||
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Check the current list of connections to see if we can
|
||||
@@ -5417,7 +5496,8 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
conn_free(conn);
|
||||
*in_connect = NULL;
|
||||
|
||||
return CURLE_NO_CONNECTION_AVAILABLE;
|
||||
result = CURLE_NO_CONNECTION_AVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
@@ -5439,7 +5519,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
*/
|
||||
result = setup_range(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
/* Continue connectdata initialization here. */
|
||||
|
||||
@@ -5457,6 +5537,12 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
*************************************************************/
|
||||
result = resolve_server(data, conn, async);
|
||||
|
||||
out:
|
||||
|
||||
Curl_safefree(options);
|
||||
Curl_safefree(passwd);
|
||||
Curl_safefree(user);
|
||||
Curl_safefree(proxy);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5666,12 +5752,18 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
conn->dns_entry = NULL;
|
||||
}
|
||||
|
||||
if(status == CURLE_ABORTED_BY_CALLBACK)
|
||||
switch(status) {
|
||||
case CURLE_ABORTED_BY_CALLBACK:
|
||||
case CURLE_READ_ERROR:
|
||||
case CURLE_WRITE_ERROR:
|
||||
/* When we're aborted due to a callback return code it basically have to
|
||||
be counted as premature as there is trouble ahead if we don't. We have
|
||||
many callbacks and protocols work differently, we could potentially do
|
||||
this more fine-grained in the future. */
|
||||
premature = TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* this calls the protocol-specific function pointer previously set */
|
||||
if(conn->handler->done)
|
||||
@@ -5728,6 +5820,7 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
this was either closed or handed over to the connection
|
||||
cache here, and therefore cannot be used from this point on
|
||||
*/
|
||||
Curl_free_request_state(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -5760,9 +5853,6 @@ static CURLcode do_init(struct connectdata *conn)
|
||||
HTTP. */
|
||||
data->set.httpreq = HTTPREQ_GET;
|
||||
|
||||
/* NB: the content encoding software depends on this initialization */
|
||||
Curl_easy_initHandleData(data);
|
||||
|
||||
k->start = Curl_tvnow(); /* start time */
|
||||
k->now = k->start; /* current time is now */
|
||||
k->header = TRUE; /* assume header */
|
||||
@@ -5861,13 +5951,3 @@ CURLcode Curl_do_more(struct connectdata *conn, int *complete)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Called on connect, and if there's already a protocol-specific struct
|
||||
allocated for a different connection, this frees it that it can be setup
|
||||
properly later on. */
|
||||
void Curl_reset_reqproto(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
Curl_safefree(data->state.proto.generic);
|
||||
data->state.proto.generic = NULL;
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_setup_conn(struct connectdata *conn,
|
||||
bool *protocol_done);
|
||||
void Curl_free_request_state(struct SessionHandle *data);
|
||||
|
||||
int Curl_protocol_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
@@ -65,11 +66,6 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data,
|
||||
|
||||
void Curl_close_connections(struct SessionHandle *data);
|
||||
|
||||
/* Called on connect, and if there's already a protocol-specific struct
|
||||
allocated for a different connection, this frees it that it can be setup
|
||||
properly later on. */
|
||||
void Curl_reset_reqproto(struct connectdata *conn);
|
||||
|
||||
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
|
||||
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
|
||||
service */
|
||||
|
@@ -222,9 +222,9 @@
|
||||
#define CURLMIN(x,y) ((x)<(y)?(x):(y))
|
||||
|
||||
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
/* Types needed for krb4/5-ftp connections */
|
||||
struct krb4buffer {
|
||||
#ifdef HAVE_GSSAPI
|
||||
/* Types needed for krb5-ftp connections */
|
||||
struct krb5buffer {
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t index;
|
||||
@@ -692,6 +692,9 @@ struct SingleRequest {
|
||||
bool forbidchunk; /* used only to explicitly forbid chunk-upload for
|
||||
specific upload buffers. See readmoredata() in
|
||||
http.c for details. */
|
||||
|
||||
void *protop; /* Allocated protocol-specific data. Each protocol
|
||||
handler makes sure this points to data it needs. */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -873,6 +876,8 @@ struct connectdata {
|
||||
char *passwd; /* password string, allocated */
|
||||
char *options; /* options string, allocated */
|
||||
|
||||
char *xoauth2_bearer; /* bearer token for xoauth2, allocated */
|
||||
|
||||
char *proxyuser; /* proxy user name string, allocated */
|
||||
char *proxypasswd; /* proxy password string, allocated */
|
||||
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
||||
@@ -931,12 +936,12 @@ struct connectdata {
|
||||
} allocptr;
|
||||
|
||||
int sec_complete; /* if kerberos is enabled for this connection */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
enum protection_level command_prot;
|
||||
enum protection_level data_prot;
|
||||
enum protection_level request_data_prot;
|
||||
size_t buffer_size;
|
||||
struct krb4buffer in_buffer;
|
||||
struct krb5buffer in_buffer;
|
||||
void *app_data;
|
||||
const struct Curl_sec_client_mech *mech;
|
||||
struct sockaddr_in local_addr;
|
||||
@@ -996,13 +1001,14 @@ struct connectdata {
|
||||
|
||||
union {
|
||||
struct ftp_conn ftpc;
|
||||
struct http_conn httpc;
|
||||
struct ssh_conn sshc;
|
||||
struct tftp_state_data *tftpc;
|
||||
struct imap_conn imapc;
|
||||
struct pop3_conn pop3c;
|
||||
struct smtp_conn smtpc;
|
||||
struct rtsp_conn rtspc;
|
||||
void *generic;
|
||||
void *generic; /* RTMP and LDAP use this */
|
||||
} proto;
|
||||
|
||||
int cselect_bits; /* bitmask of socket events */
|
||||
@@ -1149,7 +1155,6 @@ typedef enum {
|
||||
* Session-data MUST be put in the connectdata struct and here. */
|
||||
#define MAX_CURL_USER_LENGTH 256
|
||||
#define MAX_CURL_PASSWORD_LENGTH 256
|
||||
#define MAX_CURL_OPTIONS_LENGTH 256
|
||||
|
||||
struct auth {
|
||||
unsigned long want; /* Bitmask set to the authentication methods wanted by
|
||||
@@ -1274,28 +1279,6 @@ struct UrlState {
|
||||
long rtsp_next_server_CSeq; /* the session's next server CSeq */
|
||||
long rtsp_CSeq_recv; /* most recent CSeq received */
|
||||
|
||||
/* Protocol specific data.
|
||||
*
|
||||
*************************************************************************
|
||||
* Note that this data will be REMOVED after each request, so anything that
|
||||
* should be kept/stored on a per-connection basis and thus live for the
|
||||
* next request on the same connection MUST be put in the connectdata struct!
|
||||
*************************************************************************/
|
||||
union {
|
||||
struct HTTP *http;
|
||||
struct HTTP *https; /* alias, just for the sake of being more readable */
|
||||
struct RTSP *rtsp;
|
||||
struct FTP *ftp;
|
||||
/* void *tftp; not used */
|
||||
struct FILEPROTO *file;
|
||||
void *telnet; /* private for telnet.c-eyes only */
|
||||
void *generic;
|
||||
struct SSHPROTO *ssh;
|
||||
struct IMAP *imap;
|
||||
struct POP3 *pop3;
|
||||
struct SMTP *smtp;
|
||||
} proto;
|
||||
|
||||
/* if true, force SSL connection retry (workaround for certain servers) */
|
||||
bool ssl_connect_retry;
|
||||
};
|
||||
@@ -1387,6 +1370,8 @@ enum dupstring {
|
||||
STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
|
||||
#endif
|
||||
|
||||
STRING_BEARER, /* <bearer>, if used */
|
||||
|
||||
/* -- end of strings -- */
|
||||
STRING_LAST /* not used, just an end-of-list marker */
|
||||
};
|
||||
|
@@ -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
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "sslgen.h"
|
||||
#include "http2.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -122,6 +123,11 @@ char *curl_version(void)
|
||||
left -= len;
|
||||
ptr += len;
|
||||
#endif
|
||||
#ifdef USE_NGHTTP2
|
||||
len = Curl_http2_ver(ptr, left);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
#endif
|
||||
#ifdef USE_LIBRTMP
|
||||
{
|
||||
char suff[2];
|
||||
@@ -235,9 +241,6 @@ static curl_version_info_data version_info = {
|
||||
#ifdef ENABLE_IPV6
|
||||
| CURL_VERSION_IPV6
|
||||
#endif
|
||||
#ifdef HAVE_KRB4
|
||||
| CURL_VERSION_KERBEROS4
|
||||
#endif
|
||||
#ifdef USE_SSL
|
||||
| CURL_VERSION_SSL
|
||||
#endif
|
||||
@@ -277,6 +280,9 @@ static curl_version_info_data version_info = {
|
||||
#endif
|
||||
#if defined(USE_TLS_SRP)
|
||||
| CURL_VERSION_TLSAUTH_SRP
|
||||
#endif
|
||||
#if defined(USE_NGHTTP2)
|
||||
| CURL_VERSION_HTTP2
|
||||
#endif
|
||||
,
|
||||
NULL, /* ssl_version */
|
||||
|
@@ -1479,7 +1479,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_PROTOTYPE_MISMATCH], [
|
||||
return n;
|
||||
}
|
||||
]],[[
|
||||
int i[2];
|
||||
int i[2]={0,0};
|
||||
int j = rand(i[0]);
|
||||
if(j)
|
||||
return j;
|
||||
|
@@ -70,6 +70,17 @@ $ write sys$output "Can not find VMS specific Curl readme file."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$ curl_release_notes = f$search("sys$disk:[--]release-notes.")
|
||||
$ if curl_release_notes .eqs. ""
|
||||
$ then
|
||||
$ curl_release_notes = f$search("sys$disk:[--]$RELEASE-NOTES.")
|
||||
$ endif
|
||||
$ if curl_release_notes .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "Can not find Curl release-notes file."
|
||||
$ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$ if f$search("sys$disk:[]hp_ssl_release_info.txt") .eqs. ""
|
||||
$ then
|
||||
$ write sys$output "GNV_LINK_CURL.COM has not been run!"
|
||||
@@ -77,6 +88,7 @@ $ goto all_exit
|
||||
$ endif
|
||||
$!
|
||||
$ type/noheader 'curl_readme', 'vms_readme', -
|
||||
'curl_release_notes', -
|
||||
sys$disk:[]curl_release_note_start.txt, -
|
||||
sys$disk:[]hp_ssl_release_info.txt, -
|
||||
'curl_copying', -
|
||||
|
@@ -375,14 +375,24 @@ $ if f$search("''file'.obj") .nes. "" then delete/log 'file'.obj;*
|
||||
$ if f$search("''file'.opt") .nes. "" then delete/log 'file'.opt;*
|
||||
$ file = "[...]curl-*_original_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]curl_d-*_original_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]curl-*_vms_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]curl_d-*_vms_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]curl-*.release_notes"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]curl_d-*.release_notes"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]*curl*.pcsi$desc"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]*curl_d*.pcsi$desc"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]*curl*.pcsi$text"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$ file = "[...]*curl_d*.pcsi$text"
|
||||
$ if f$search(file) .nes. "" then delete/log 'file';*
|
||||
$!
|
||||
$ if clean_all .eq. 0 then goto Common_Exit
|
||||
$ endif
|
||||
|
@@ -108,15 +108,36 @@ $!
|
||||
$ file = "lcl_root:[.include.curl]curlbuild.h_old"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl-*_original_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl_d-*_original_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl-*_vms_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl_d-*_vms_src.bck"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl-*.release_notes"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]curl_d-*.release_notes"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$desc"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]*-curl_d-*.pcsi$desc"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$text"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$ file = "lcl_root:[.packages.vms]*-curl_d-*.pcsi$text"
|
||||
$ if f$search(file) .nes. "" then delete 'file';*
|
||||
$!
|
||||
$!======================================================================
|
||||
$!
|
||||
$ if p1 .nes. "REALCLEAN" then goto all_exit
|
||||
|
@@ -57,6 +57,11 @@ void free_config_fields(struct Configurable *config)
|
||||
Curl_safefree(config->proxyuserpwd);
|
||||
Curl_safefree(config->proxy);
|
||||
|
||||
Curl_safefree(config->dns_ipv6_addr);
|
||||
Curl_safefree(config->dns_ipv4_addr);
|
||||
Curl_safefree(config->dns_interface);
|
||||
Curl_safefree(config->dns_servers);
|
||||
|
||||
Curl_safefree(config->noproxy);
|
||||
|
||||
Curl_safefree(config->mail_from);
|
||||
@@ -96,6 +101,8 @@ void free_config_fields(struct Configurable *config)
|
||||
Curl_safefree(config->krblevel);
|
||||
Curl_safefree(config->trace_dump);
|
||||
|
||||
Curl_safefree(config->xoauth2_bearer);
|
||||
|
||||
config->trace_stream = NULL; /* closed elsewhere when appropriate */
|
||||
|
||||
Curl_safefree(config->writeout);
|
||||
@@ -125,4 +132,3 @@ void free_config_fields(struct Configurable *config)
|
||||
|
||||
Curl_safefree(config->libcurl);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
@@ -66,6 +66,10 @@ struct Configurable {
|
||||
char *range;
|
||||
long low_speed_limit;
|
||||
long low_speed_time;
|
||||
char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
|
||||
char *dns_interface; /* interface name */
|
||||
char *dns_ipv4_addr; /* dot notation */
|
||||
char *dns_ipv6_addr; /* dot notation */
|
||||
int showerror; /* -1 == unset, default => show errors
|
||||
0 => -s is used to NOT show errors
|
||||
1 => -S has been used to show errors */
|
||||
@@ -205,9 +209,12 @@ struct Configurable {
|
||||
bool use_metalink; /* process given URLs as metalink XML file */
|
||||
metalinkfile *metalinkfile_list; /* point to the first node */
|
||||
metalinkfile *metalinkfile_last; /* point to the last/current node */
|
||||
#ifdef CURLDEBUG
|
||||
bool test_event_based;
|
||||
#endif
|
||||
char *xoauth2_bearer; /* XOAUTH2 bearer token */
|
||||
}; /* struct Configurable */
|
||||
|
||||
void free_config_fields(struct Configurable *config);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_CFGABLE_H */
|
||||
|
||||
|
@@ -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
|
||||
@@ -73,10 +73,14 @@ static const struct LongShort aliases[]= {
|
||||
/* all these ones, starting with "*" or "$" as a short-option have *no*
|
||||
short option to mention. */
|
||||
{"*", "url", TRUE},
|
||||
{"*4", "dns-ipv4-addr", TRUE},
|
||||
{"*6", "dns-ipv6-addr", TRUE},
|
||||
{"*a", "random-file", TRUE},
|
||||
{"*b", "egd-file", TRUE},
|
||||
{"*B", "oauth2-bearer", TRUE},
|
||||
{"*c", "connect-timeout", TRUE},
|
||||
{"*d", "ciphers", TRUE},
|
||||
{"*D", "dns-interface", TRUE},
|
||||
{"*e", "disable-epsv", FALSE},
|
||||
{"*E", "epsv", FALSE},
|
||||
/* 'epsv' made like this to make --no-epsv and --epsv to work
|
||||
@@ -84,6 +88,7 @@ static const struct LongShort aliases[]= {
|
||||
#ifdef USE_ENVIRONMENT
|
||||
{"*f", "environment", FALSE},
|
||||
#endif
|
||||
{"*F", "dns-servers", TRUE},
|
||||
{"*g", "trace", TRUE},
|
||||
{"*h", "trace-ascii", TRUE},
|
||||
{"*i", "limit-rate", TRUE},
|
||||
@@ -174,7 +179,10 @@ static const struct LongShort aliases[]= {
|
||||
{"$I", "post303", FALSE},
|
||||
{"$J", "metalink", FALSE},
|
||||
{"$K", "sasl-ir", FALSE},
|
||||
{"$L", "test-event", FALSE},
|
||||
{"0", "http1.0", FALSE},
|
||||
{"01", "http1.1", FALSE},
|
||||
{"02", "http2.0", FALSE},
|
||||
{"1", "tlsv1", FALSE},
|
||||
{"2", "sslv2", FALSE},
|
||||
{"3", "sslv3", FALSE},
|
||||
@@ -283,7 +291,8 @@ static const struct feat feats[] = {
|
||||
{"krb4", CURL_VERSION_KERBEROS4},
|
||||
{"libz", CURL_VERSION_LIBZ},
|
||||
{"CharConv", CURL_VERSION_CONV},
|
||||
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
|
||||
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
|
||||
{"HTTP2", CURL_VERSION_HTTP2}
|
||||
};
|
||||
|
||||
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
|
||||
@@ -491,12 +500,23 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
switch(letter) {
|
||||
case '*': /* options without a short option */
|
||||
switch(subletter) {
|
||||
case '4': /* --dns-ipv4-addr */
|
||||
/* addr in dot notation */
|
||||
GetStr(&config->dns_ipv4_addr, nextarg);
|
||||
break;
|
||||
case '6': /* --dns-ipv6-addr */
|
||||
/* addr in dot notation */
|
||||
GetStr(&config->dns_ipv6_addr, nextarg);
|
||||
break;
|
||||
case 'a': /* random-file */
|
||||
GetStr(&config->random_file, nextarg);
|
||||
break;
|
||||
case 'b': /* egd-file */
|
||||
GetStr(&config->egd_file, nextarg);
|
||||
break;
|
||||
case 'B': /* XOAUTH2 Bearer */
|
||||
GetStr(&config->xoauth2_bearer, nextarg);
|
||||
break;
|
||||
case 'c': /* connect-timeout */
|
||||
err = str2udouble(&config->connecttimeout, nextarg);
|
||||
if(err)
|
||||
@@ -505,6 +525,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'd': /* ciphers */
|
||||
GetStr(&config->cipher_list, nextarg);
|
||||
break;
|
||||
case 'D': /* --dns-interface */
|
||||
/* interface name */
|
||||
GetStr(&config->dns_interface, nextarg);
|
||||
break;
|
||||
case 'e': /* --disable-epsv */
|
||||
config->disable_epsv = toggle;
|
||||
break;
|
||||
@@ -516,6 +540,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
config->writeenv = toggle;
|
||||
break;
|
||||
#endif
|
||||
case 'F': /* --dns-servers */
|
||||
/* IP addrs of DNS servers */
|
||||
GetStr(&config->dns_servers, nextarg);
|
||||
break;
|
||||
case 'g': /* --trace */
|
||||
GetStr(&config->trace_dump, nextarg);
|
||||
if(config->tracetype && (config->tracetype != TRACE_BIN))
|
||||
@@ -639,7 +667,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
|
||||
case 'r': /* --create-dirs */
|
||||
config->create_dirs = TRUE;
|
||||
config->create_dirs = toggle;
|
||||
break;
|
||||
|
||||
case 's': /* --max-redirs */
|
||||
@@ -661,7 +689,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
|
||||
case 'u': /* --crlf */
|
||||
/* LF -> CRLF conversion? */
|
||||
config->crlf = TRUE;
|
||||
config->crlf = toggle;
|
||||
break;
|
||||
|
||||
case 'v': /* --stderr */
|
||||
@@ -888,7 +916,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
GetStr(&config->socks5_gssapi_service, nextarg);
|
||||
break;
|
||||
case '7': /* --socks5-gssapi-nec*/
|
||||
config->socks5_gssapi_nec = TRUE;
|
||||
config->socks5_gssapi_nec = toggle;
|
||||
break;
|
||||
#endif
|
||||
case '8': /* --proxy1.0 */
|
||||
@@ -959,7 +987,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
}
|
||||
case 'K': /* --sasl-ir */
|
||||
config->sasl_ir = TRUE;
|
||||
config->sasl_ir = toggle;
|
||||
break;
|
||||
case 'L': /* --test-event */
|
||||
#ifdef CURLDEBUG
|
||||
config->test_event_based = toggle;
|
||||
#else
|
||||
warnf(config, "--test-event is ignored unless a debug build!\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -972,10 +1007,22 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case '~': /* --xattr */
|
||||
config->xattr = toggle;
|
||||
break;
|
||||
case '0':
|
||||
case '0': /* --http* options */
|
||||
switch(subletter) {
|
||||
case '\0':
|
||||
/* HTTP version 1.0 */
|
||||
config->httpversion = CURL_HTTP_VERSION_1_0;
|
||||
break;
|
||||
case '1':
|
||||
/* HTTP version 1.1 */
|
||||
config->httpversion = CURL_HTTP_VERSION_1_1;
|
||||
break;
|
||||
case '2':
|
||||
/* HTTP version 2.0 */
|
||||
config->httpversion = CURL_HTTP_VERSION_2_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
/* TLS version 1 */
|
||||
config->ssl_version = CURL_SSLVERSION_TLSv1;
|
||||
@@ -1621,20 +1668,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
/* user:password */
|
||||
/* user:password;options */
|
||||
GetStr(&config->userpwd, nextarg);
|
||||
cleanarg(nextarg);
|
||||
err = checkpasswd("host", &config->userpwd);
|
||||
if(err)
|
||||
return err;
|
||||
break;
|
||||
case 'U':
|
||||
/* Proxy user:password */
|
||||
GetStr(&config->proxyuserpwd, nextarg);
|
||||
cleanarg(nextarg);
|
||||
err = checkpasswd("proxy", &config->proxyuserpwd);
|
||||
if(err)
|
||||
return err;
|
||||
break;
|
||||
case 'v':
|
||||
if(toggle) {
|
||||
@@ -1781,4 +1822,3 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
|
||||
return PARAM_OK;
|
||||
}
|
||||
|
||||
|
@@ -69,6 +69,10 @@ static const char *const helptext[] = {
|
||||
" --digest Use HTTP Digest Authentication (H)",
|
||||
" --disable-eprt Inhibit using EPRT or LPRT (F)",
|
||||
" --disable-epsv Inhibit using EPSV (F)",
|
||||
" --dns-servers DNS server addrs to use: 1.1.1.1;2.2.2.2",
|
||||
" --dns-interface Interface to use for DNS requests",
|
||||
" --dns-ipv4-addr IPv4 address to use for DNS requests, dot notation",
|
||||
" --dns-ipv6-addr IPv6 address to use for DNS requests, dot notation",
|
||||
" -D, --dump-header FILE Write the headers to this file",
|
||||
" --egd-file FILE EGD socket path for random data (SSL)",
|
||||
" --engine ENGINE Crypto engine (SSL). \"--engine list\" for list",
|
||||
@@ -99,6 +103,8 @@ static const char *const helptext[] = {
|
||||
" --hostpubmd5 MD5 "
|
||||
"Hex encoded MD5 string of the host public key. (SSH)",
|
||||
" -0, --http1.0 Use HTTP 1.0 (H)",
|
||||
" --http1.1 Use HTTP 1.1 (H)",
|
||||
" --http2.0 Use HTTP 2.0 (H)",
|
||||
" --ignore-content-length Ignore the HTTP Content-Length header",
|
||||
" -i, --include Include protocol headers in the output (H/F)",
|
||||
" -k, --insecure Allow connections to SSL sites without certs (H)",
|
||||
@@ -119,9 +125,9 @@ static const char *const helptext[] = {
|
||||
" -L, --location Follow redirects (H)",
|
||||
" --location-trusted like --location and send auth to other hosts (H)",
|
||||
" -M, --manual Display the full manual",
|
||||
" --mail-from FROM Mail from this address",
|
||||
" --mail-rcpt TO Mail to this receiver(s)",
|
||||
" --mail-auth AUTH Originator address of the original email",
|
||||
" --mail-from FROM Mail from this address (SMTP)",
|
||||
" --mail-rcpt TO Mail to this/these addresses (SMTP)",
|
||||
" --mail-auth AUTH Originator address of the original email (SMTP)",
|
||||
" --max-filesize BYTES Maximum file size to download (H/F)",
|
||||
" --max-redirs NUM Maximum number of redirects allowed (H)",
|
||||
" -m, --max-time SECONDS Maximum time allowed for the transfer",
|
||||
@@ -135,6 +141,7 @@ static const char *const helptext[] = {
|
||||
" --no-sessionid Disable SSL session-ID reusing (SSL)",
|
||||
" --noproxy List of hosts which do not use proxy",
|
||||
" --ntlm Use HTTP NTLM authentication (H)",
|
||||
" --oauth2-bearer BEARER XOAUTH2 Bearer Token (IMAP, POP3, SMTP)",
|
||||
" -o, --output FILE Write output to <file> instead of stdout",
|
||||
" --pass PASS Pass phrase for the private key (SSL/SSH)",
|
||||
" --post301 "
|
||||
@@ -173,7 +180,7 @@ static const char *const helptext[] = {
|
||||
" --retry-delay SECONDS "
|
||||
"When retrying, wait this many seconds between each",
|
||||
" --retry-max-time SECONDS Retry only within this period",
|
||||
" --sasl-ir Enable initial response in SASL authentication"
|
||||
" --sasl-ir Enable initial response in SASL authentication",
|
||||
" -S, --show-error "
|
||||
"Show error. With -s, make curl show errors when they occur",
|
||||
" -s, --silent Silent mode. Don't output anything",
|
||||
@@ -243,4 +250,3 @@ void tool_help(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -69,6 +69,7 @@
|
||||
#include "tool_msgs.h"
|
||||
#include "tool_operate.h"
|
||||
#include "tool_operhlp.h"
|
||||
#include "tool_paramhlp.h"
|
||||
#include "tool_parsecfg.h"
|
||||
#include "tool_setopt.h"
|
||||
#include "tool_sleep.h"
|
||||
@@ -81,6 +82,11 @@
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/* libcurl's debug builds provide an extra function */
|
||||
CURLcode curl_easy_perform_ev(CURL *easy);
|
||||
#endif
|
||||
|
||||
#define CURLseparator "--_curl_--"
|
||||
|
||||
#ifndef O_BINARY
|
||||
@@ -196,6 +202,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
bool stillflags;
|
||||
int res = 0;
|
||||
int i;
|
||||
unsigned long li;
|
||||
|
||||
bool orig_noprogress;
|
||||
bool orig_isatty;
|
||||
@@ -319,6 +326,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if(config->userpwd && !config->xoauth2_bearer) {
|
||||
res = checkpasswd("host", &config->userpwd);
|
||||
if(res)
|
||||
goto quit_curl;
|
||||
}
|
||||
|
||||
if(config->proxyuserpwd) {
|
||||
res = checkpasswd("proxy", &config->proxyuserpwd);
|
||||
if(res)
|
||||
goto quit_curl;
|
||||
}
|
||||
|
||||
if((!config->url_list || !config->url_list->url) && !config->list_engines) {
|
||||
helpf(config->errors, "no URL specified!\n");
|
||||
res = CURLE_FAILED_INIT;
|
||||
@@ -465,10 +484,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
|
||||
for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
|
||||
|
||||
int up; /* upload file counter within a single upload glob */
|
||||
unsigned long up; /* upload file counter within a single upload glob */
|
||||
char *infiles; /* might be a glob pattern */
|
||||
char *outfiles;
|
||||
int infilenum;
|
||||
unsigned long infilenum;
|
||||
URLGlob *inglob;
|
||||
|
||||
int metalink = 0; /* nonzero for metalink download. */
|
||||
@@ -533,7 +552,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
char *uploadfile; /* a single file, never a glob */
|
||||
int separator;
|
||||
URLGlob *urls;
|
||||
int urlnum;
|
||||
unsigned long urlnum;
|
||||
|
||||
uploadfile = NULL;
|
||||
urls = NULL;
|
||||
@@ -583,7 +602,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
|
||||
|
||||
/* Here's looping around each globbed URL */
|
||||
for(i = 0 ; i < urlnum; i++) {
|
||||
for(li = 0 ; li < urlnum; li++) {
|
||||
|
||||
int infd;
|
||||
bool infdopen;
|
||||
@@ -628,7 +647,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
if(res)
|
||||
goto show_error;
|
||||
}
|
||||
else if(!i) {
|
||||
else if(!li) {
|
||||
this_url = strdup(urlnode->url);
|
||||
if(!this_url) {
|
||||
res = CURLE_OUT_OF_MEMORY;
|
||||
@@ -863,8 +882,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
}
|
||||
|
||||
if(urlnum > 1 && !(config->mute)) {
|
||||
fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
|
||||
i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
|
||||
fprintf(config->errors, "\n[%lu/%lu]: %s --> %s\n",
|
||||
li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
|
||||
if(separator)
|
||||
printf("%s%s\n", CURLseparator, this_url);
|
||||
}
|
||||
@@ -971,6 +990,9 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
else if(!config->use_metalink)
|
||||
my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L);
|
||||
|
||||
if(config->xoauth2_bearer)
|
||||
my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->xoauth2_bearer);
|
||||
|
||||
#if !defined(CURL_DISABLE_PROXY)
|
||||
{
|
||||
/* TODO: Make this a run-time check instead of compile-time one. */
|
||||
@@ -1217,6 +1239,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
|
||||
}
|
||||
|
||||
/* new in libcurl 7.24.0: */
|
||||
if(config->dns_servers)
|
||||
my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
|
||||
|
||||
/* new in libcurl 7.33.0: */
|
||||
if(config->dns_interface)
|
||||
my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
|
||||
if(config->dns_ipv4_addr)
|
||||
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
|
||||
if(config->dns_ipv6_addr)
|
||||
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
|
||||
|
||||
/* new in libcurl 7.6.2: */
|
||||
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
|
||||
|
||||
@@ -1449,6 +1483,11 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
mlfile->filename, this_url);
|
||||
#endif /* USE_METALINK */
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
if(config->test_event_based)
|
||||
res = curl_easy_perform_ev(curl);
|
||||
else
|
||||
#endif
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(outs.is_cd_filename && outs.stream && !config->mute &&
|
||||
@@ -1872,4 +1911,3 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -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,141 +31,146 @@
|
||||
|
||||
typedef enum {
|
||||
GLOB_OK,
|
||||
GLOB_NO_MEM,
|
||||
GLOB_ERROR
|
||||
GLOB_NO_MEM = CURLE_OUT_OF_MEMORY,
|
||||
GLOB_ERROR = CURLE_URL_MALFORMAT
|
||||
} GlobCode;
|
||||
|
||||
/*
|
||||
* glob_word()
|
||||
*
|
||||
* Input a full globbed string, set the forth argument to the amount of
|
||||
* strings we get out of this. Return GlobCode.
|
||||
*/
|
||||
static GlobCode glob_word(URLGlob *, /* object anchor */
|
||||
char *, /* globbed string */
|
||||
size_t, /* position */
|
||||
int *); /* returned number of strings */
|
||||
#define GLOBERROR(string, column, code) \
|
||||
glob->error = string, glob->pos = column, code;
|
||||
|
||||
static GlobCode glob_set(URLGlob *glob, char *pattern,
|
||||
size_t pos, int *amount)
|
||||
void glob_cleanup(URLGlob* glob);
|
||||
|
||||
static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
|
||||
{
|
||||
URLPattern *pat = &glob->pattern[glob->size];
|
||||
pat->type = UPTSet;
|
||||
pat->content.Set.size = 1;
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->globindex = -1;
|
||||
|
||||
(*amount)++;
|
||||
|
||||
pat->content.Set.elements = malloc(sizeof(char*));
|
||||
|
||||
if(!pat->content.Set.elements)
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
|
||||
pat->content.Set.elements[0] = strdup(glob->glob_buffer);
|
||||
if(!pat->content.Set.elements[0])
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
|
||||
return GLOB_OK;
|
||||
}
|
||||
|
||||
/* multiply
|
||||
*
|
||||
* Multiplies and checks for overflow.
|
||||
*/
|
||||
static int multiply(unsigned long *amount, long with)
|
||||
{
|
||||
unsigned long sum = *amount * with;
|
||||
if(sum/with != *amount)
|
||||
return 1; /* didn't fit, bail out */
|
||||
*amount = sum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GlobCode glob_set(URLGlob *glob, char **patternp,
|
||||
size_t *posp, unsigned long *amount,
|
||||
int globindex)
|
||||
{
|
||||
/* processes a set expression with the point behind the opening '{'
|
||||
','-separated elements are collected until the next closing '}'
|
||||
*/
|
||||
URLPattern *pat;
|
||||
GlobCode res;
|
||||
bool done = FALSE;
|
||||
char *buf = glob->glob_buffer;
|
||||
char *pattern = *patternp;
|
||||
char *opattern = pattern;
|
||||
size_t opos = *posp-1;
|
||||
|
||||
pat = &glob->pattern[glob->size / 2];
|
||||
pat = &glob->pattern[glob->size];
|
||||
/* patterns 0,1,2,... correspond to size=1,3,5,... */
|
||||
pat->type = UPTSet;
|
||||
pat->content.Set.size = 0;
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->content.Set.elements = NULL;
|
||||
|
||||
if(++glob->size > (GLOB_PATTERN_NUM*2)) {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n");
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
pat->globindex = globindex;
|
||||
|
||||
while(!done) {
|
||||
switch (*pattern) {
|
||||
case '\0': /* URL ended while set was still open */
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"unmatched brace at pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
return GLOBERROR("unmatched brace", opos, GLOB_ERROR);
|
||||
|
||||
case '{':
|
||||
case '[': /* no nested expressions at this time */
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"nested braces not supported at pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
return GLOBERROR("nested brace", *posp, GLOB_ERROR);
|
||||
|
||||
case ',':
|
||||
case '}': /* set element completed */
|
||||
if(opattern == pattern)
|
||||
return GLOBERROR("empty string within braces", *posp, GLOB_ERROR);
|
||||
|
||||
/* add 1 to size since it'll be incremented below */
|
||||
if(multiply(amount, pat->content.Set.size+1))
|
||||
return GLOBERROR("range overflow", 0, GLOB_ERROR);
|
||||
|
||||
/* fall-through */
|
||||
case ',':
|
||||
|
||||
*buf = '\0';
|
||||
if(pat->content.Set.elements) {
|
||||
char **new_arr = realloc(pat->content.Set.elements,
|
||||
(pat->content.Set.size + 1) * sizeof(char*));
|
||||
if(!new_arr) {
|
||||
short elem;
|
||||
for(elem = 0; elem < pat->content.Set.size; elem++)
|
||||
Curl_safefree(pat->content.Set.elements[elem]);
|
||||
Curl_safefree(pat->content.Set.elements);
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->content.Set.size = 0;
|
||||
}
|
||||
if(!new_arr)
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
|
||||
pat->content.Set.elements = new_arr;
|
||||
}
|
||||
else
|
||||
pat->content.Set.elements = malloc(sizeof(char*));
|
||||
if(!pat->content.Set.elements) {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
||||
return GLOB_NO_MEM;
|
||||
}
|
||||
|
||||
if(!pat->content.Set.elements)
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
|
||||
pat->content.Set.elements[pat->content.Set.size] =
|
||||
strdup(glob->glob_buffer);
|
||||
if(!pat->content.Set.elements[pat->content.Set.size]) {
|
||||
short elem;
|
||||
for(elem = 0; elem < pat->content.Set.size; elem++)
|
||||
Curl_safefree(pat->content.Set.elements[elem]);
|
||||
Curl_safefree(pat->content.Set.elements);
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->content.Set.size = 0;
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
||||
return GLOB_NO_MEM;
|
||||
}
|
||||
if(!pat->content.Set.elements[pat->content.Set.size])
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
++pat->content.Set.size;
|
||||
|
||||
if(*pattern == '}') {
|
||||
/* entire set pattern completed */
|
||||
int wordamount;
|
||||
|
||||
/* always check for a literal (may be "") between patterns */
|
||||
res = glob_word(glob, ++pattern, ++pos, &wordamount);
|
||||
if(res) {
|
||||
short elem;
|
||||
for(elem = 0; elem < pat->content.Set.size; elem++)
|
||||
Curl_safefree(pat->content.Set.elements[elem]);
|
||||
Curl_safefree(pat->content.Set.elements);
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->content.Set.size = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
*amount = pat->content.Set.size * wordamount;
|
||||
|
||||
pattern++; /* pass the closing brace */
|
||||
done = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = glob->glob_buffer;
|
||||
++pattern;
|
||||
++pos;
|
||||
++(*posp);
|
||||
break;
|
||||
|
||||
case ']': /* illegal closing bracket */
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"illegal pattern at pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
return GLOBERROR("unexpected close bracket", *posp, GLOB_ERROR);
|
||||
|
||||
case '\\': /* escaped character, skip '\' */
|
||||
if(pattern[1]) {
|
||||
++pattern;
|
||||
++pos;
|
||||
++(*posp);
|
||||
}
|
||||
/* intentional fallthrough */
|
||||
default:
|
||||
*buf++ = *pattern++; /* copy character to set element */
|
||||
++pos;
|
||||
++(*posp);
|
||||
}
|
||||
}
|
||||
|
||||
*patternp = pattern; /* return with the new position */
|
||||
return GLOB_OK;
|
||||
}
|
||||
|
||||
static GlobCode glob_range(URLGlob *glob, char *pattern,
|
||||
size_t pos, int *amount)
|
||||
static GlobCode glob_range(URLGlob *glob, char **patternp,
|
||||
size_t *posp, unsigned long *amount,
|
||||
int globindex)
|
||||
{
|
||||
/* processes a range expression with the point behind the opening '['
|
||||
- char range: e.g. "a-z]", "B-Q]"
|
||||
@@ -174,77 +179,68 @@ static GlobCode glob_range(URLGlob *glob, char *pattern,
|
||||
expression is checked for well-formedness and collected until the next ']'
|
||||
*/
|
||||
URLPattern *pat;
|
||||
char *c;
|
||||
char sep;
|
||||
char sep2;
|
||||
int step;
|
||||
int rc;
|
||||
GlobCode res;
|
||||
int wordamount = 1;
|
||||
char *pattern = *patternp;
|
||||
char *c;
|
||||
|
||||
pat = &glob->pattern[glob->size / 2];
|
||||
/* patterns 0,1,2,... correspond to size=1,3,5,... */
|
||||
if(++glob->size > (GLOB_PATTERN_NUM*2)) {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n");
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
pat = &glob->pattern[glob->size];
|
||||
pat->globindex = globindex;
|
||||
|
||||
if(ISALPHA(*pattern)) {
|
||||
/* character range detected */
|
||||
char min_c;
|
||||
char max_c;
|
||||
int step=1;
|
||||
|
||||
pat->type = UPTCharRange;
|
||||
|
||||
rc = sscanf(pattern, "%c-%c%c%d%c", &min_c, &max_c, &sep, &step, &sep2);
|
||||
rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
|
||||
|
||||
if((rc < 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a'))) {
|
||||
if((rc == 2) && (pattern[3] == ':')) {
|
||||
char *endp;
|
||||
unsigned long lstep;
|
||||
errno = 0;
|
||||
lstep = strtoul(&pattern[3], &endp, 10);
|
||||
if(errno || (*endp != ']'))
|
||||
step = -1;
|
||||
else {
|
||||
pattern = endp+1;
|
||||
step = (int)lstep;
|
||||
if(step > (max_c - min_c))
|
||||
step = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
pattern+=3;
|
||||
|
||||
*posp += (pattern - *patternp);
|
||||
|
||||
if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
|
||||
(step < 0) )
|
||||
/* the pattern is not well-formed */
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"error: bad range specification after pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
|
||||
/* check the (first) separating character */
|
||||
if((sep != ']') && (sep != ':')) {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"error: unsupported character (%c) after range at pos %zu\n",
|
||||
sep, pos);
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
return GLOBERROR("bad range", *posp, GLOB_ERROR);
|
||||
|
||||
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
||||
pat->content.CharRange.step =
|
||||
((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1;
|
||||
|
||||
pat->content.CharRange.step = step;
|
||||
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
|
||||
pat->content.CharRange.max_c = max_c;
|
||||
|
||||
if(multiply(amount, (pat->content.CharRange.max_c -
|
||||
pat->content.CharRange.min_c + 1)))
|
||||
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
|
||||
}
|
||||
else if(ISDIGIT(*pattern)) {
|
||||
/* numeric range detected */
|
||||
int min_n;
|
||||
int max_n;
|
||||
unsigned long min_n;
|
||||
unsigned long max_n = 0;
|
||||
unsigned long step_n = 0;
|
||||
char *endp;
|
||||
|
||||
pat->type = UPTNumRange;
|
||||
pat->content.NumRange.padlength = 0;
|
||||
|
||||
rc = sscanf(pattern, "%d-%d%c%d%c", &min_n, &max_n, &sep, &step, &sep2);
|
||||
|
||||
if((rc < 2) || (min_n > max_n)) {
|
||||
/* the pattern is not well-formed */
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"error: bad range specification after pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
|
||||
pat->content.NumRange.max_n = max_n;
|
||||
|
||||
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
||||
pat->content.NumRange.step =
|
||||
((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1;
|
||||
|
||||
if(*pattern == '0') {
|
||||
/* leading zero specified */
|
||||
/* leading zero specified, count them! */
|
||||
c = pattern;
|
||||
while(ISDIGIT(*c)) {
|
||||
c++;
|
||||
@@ -252,59 +248,74 @@ static GlobCode glob_range(URLGlob *glob, char *pattern,
|
||||
instances of this pattern */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
min_n = strtoul(pattern, &endp, 10);
|
||||
if(errno || (endp == pattern))
|
||||
endp=NULL;
|
||||
else {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"illegal character in range specification at pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
|
||||
c = (char*)strchr(pattern, ']'); /* continue after next ']' */
|
||||
if(c)
|
||||
c++;
|
||||
if(*endp != '-')
|
||||
endp = NULL;
|
||||
else {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'");
|
||||
return GLOB_ERROR; /* missing ']' */
|
||||
pattern = endp+1;
|
||||
errno = 0;
|
||||
max_n = strtoul(pattern, &endp, 10);
|
||||
if(errno || (*endp == ':')) {
|
||||
pattern = endp+1;
|
||||
errno = 0;
|
||||
step_n = strtoul(pattern, &endp, 10);
|
||||
if(errno)
|
||||
/* over/underflow situation */
|
||||
endp = NULL;
|
||||
}
|
||||
|
||||
/* always check for a literal (may be "") between patterns */
|
||||
|
||||
res = glob_word(glob, c, pos + (c - pattern), &wordamount);
|
||||
if(res == GLOB_ERROR) {
|
||||
wordamount = 1;
|
||||
res = GLOB_OK;
|
||||
}
|
||||
|
||||
if(!res) {
|
||||
if(pat->type == UPTCharRange)
|
||||
*amount = wordamount * (pat->content.CharRange.max_c -
|
||||
pat->content.CharRange.min_c + 1);
|
||||
else
|
||||
*amount = wordamount * (pat->content.NumRange.max_n -
|
||||
pat->content.NumRange.min_n + 1);
|
||||
step_n = 1;
|
||||
if(endp && (*endp == ']')) {
|
||||
pattern= endp+1;
|
||||
}
|
||||
else
|
||||
endp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return res; /* GLOB_OK or GLOB_NO_MEM */
|
||||
*posp += (pattern - *patternp);
|
||||
|
||||
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)))
|
||||
/* the pattern is not well-formed */
|
||||
return GLOBERROR("bad range", *posp, GLOB_ERROR);
|
||||
|
||||
/* typecasting to ints are fine here since we make sure above that we
|
||||
are within 31 bits */
|
||||
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
|
||||
pat->content.NumRange.max_n = max_n;
|
||||
pat->content.NumRange.step = step_n;
|
||||
|
||||
if(multiply(amount, (pat->content.NumRange.max_n -
|
||||
pat->content.NumRange.min_n + 1)))
|
||||
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
|
||||
}
|
||||
else
|
||||
return GLOBERROR("bad range specification", *posp, GLOB_ERROR);
|
||||
|
||||
*patternp = pattern;
|
||||
return GLOB_OK;
|
||||
}
|
||||
|
||||
static GlobCode glob_word(URLGlob *glob, char *pattern,
|
||||
size_t pos, int *amount)
|
||||
static GlobCode glob_parse(URLGlob *glob, char *pattern,
|
||||
size_t pos, unsigned long *amount)
|
||||
{
|
||||
/* processes a literal string component of a URL
|
||||
special characters '{' and '[' branch to set/range processing functions
|
||||
*/
|
||||
char* buf = glob->glob_buffer;
|
||||
size_t litindex;
|
||||
GlobCode res = GLOB_OK;
|
||||
int globindex = 0; /* count "actual" globs */
|
||||
|
||||
*amount = 1; /* default is one single string */
|
||||
|
||||
while(*pattern != '\0' && *pattern != '{' && *pattern != '[') {
|
||||
if(*pattern == '}' || *pattern == ']') {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
||||
"unmatched close brace/bracket at pos %zu\n", pos);
|
||||
return GLOB_ERROR;
|
||||
}
|
||||
while(*pattern && !res) {
|
||||
int sublen = 0;
|
||||
while(*pattern && *pattern != '{' && *pattern != '[') {
|
||||
if(*pattern == '}' || *pattern == ']')
|
||||
return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR);
|
||||
|
||||
/* only allow \ to escape known "special letters" */
|
||||
if(*pattern == '\\' &&
|
||||
@@ -317,47 +328,51 @@ static GlobCode glob_word(URLGlob *glob, char *pattern,
|
||||
}
|
||||
*buf++ = *pattern++; /* copy character to literal */
|
||||
++pos;
|
||||
sublen++;
|
||||
}
|
||||
if(sublen) {
|
||||
/* we got a literal string, add it as a single-item list */
|
||||
*buf = '\0';
|
||||
litindex = glob->size / 2;
|
||||
/* literals 0,1,2,... correspond to size=0,2,4,... */
|
||||
glob->literal[litindex] = strdup(glob->glob_buffer);
|
||||
if(!glob->literal[litindex]) {
|
||||
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
|
||||
return GLOB_NO_MEM;
|
||||
res = glob_fixed(glob, amount);
|
||||
}
|
||||
++glob->size;
|
||||
else {
|
||||
if(!*amount)
|
||||
*amount = 1;
|
||||
|
||||
switch (*pattern) {
|
||||
case '\0':
|
||||
/* singular URL processed */
|
||||
case '\0': /* done */
|
||||
break;
|
||||
|
||||
case '{':
|
||||
/* process set pattern */
|
||||
res = glob_set(glob, ++pattern, ++pos, amount);
|
||||
pattern++;
|
||||
pos++;
|
||||
res = glob_set(glob, &pattern, &pos, amount, globindex++);
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* process range pattern */
|
||||
res = glob_range(glob, ++pattern, ++pos, amount);
|
||||
pattern++;
|
||||
pos++;
|
||||
res = glob_range(glob, &pattern, &pos, amount, globindex++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(res)
|
||||
Curl_safefree(glob->literal[litindex]);
|
||||
|
||||
if(++glob->size > GLOB_PATTERN_NUM)
|
||||
return GLOBERROR("too many globs", pos, GLOB_ERROR);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error)
|
||||
int glob_url(URLGlob** glob, char* url, unsigned long *urlnum, FILE *error)
|
||||
{
|
||||
/*
|
||||
* We can deal with any-size, just make a buffer with the same length
|
||||
* as the specified URL!
|
||||
*/
|
||||
URLGlob *glob_expand;
|
||||
int amount;
|
||||
unsigned long amount = 0;
|
||||
char *glob_buffer;
|
||||
GlobCode res;
|
||||
|
||||
@@ -372,26 +387,31 @@ int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error)
|
||||
Curl_safefree(glob_buffer);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
glob_expand->size = 0;
|
||||
glob_expand->urllen = strlen(url);
|
||||
glob_expand->glob_buffer = glob_buffer;
|
||||
glob_expand->beenhere = 0;
|
||||
|
||||
res = glob_word(glob_expand, url, 1, &amount);
|
||||
res = glob_parse(glob_expand, url, 1, &amount);
|
||||
if(!res)
|
||||
*urlnum = amount;
|
||||
else {
|
||||
if(error && glob_expand->errormsg[0]) {
|
||||
if(error && glob_expand->error) {
|
||||
char text[128];
|
||||
const char *t;
|
||||
if(glob_expand->pos) {
|
||||
snprintf(text, sizeof(text), "%s in column %zu", glob_expand->error,
|
||||
glob_expand->pos);
|
||||
t = text;
|
||||
}
|
||||
else
|
||||
t = glob_expand->error;
|
||||
|
||||
/* send error description to the error-stream */
|
||||
fprintf(error, "curl: (%d) [globbing] %s",
|
||||
(res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT,
|
||||
glob_expand->errormsg);
|
||||
fprintf(error, "curl: (%d) [globbing] %s\n", res, t);
|
||||
}
|
||||
/* it failed, we cleanup */
|
||||
Curl_safefree(glob_buffer);
|
||||
Curl_safefree(glob_expand);
|
||||
glob_cleanup(glob_expand);
|
||||
*urlnum = 1;
|
||||
return (res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT;
|
||||
return res;
|
||||
}
|
||||
|
||||
*glob = glob_expand;
|
||||
@@ -404,19 +424,14 @@ void glob_cleanup(URLGlob* glob)
|
||||
int elem;
|
||||
|
||||
for(i = glob->size - 1; i < glob->size; --i) {
|
||||
if(!(i & 1)) { /* even indexes contain literals */
|
||||
Curl_safefree(glob->literal[i/2]);
|
||||
}
|
||||
else { /* odd indexes contain sets or ranges */
|
||||
if((glob->pattern[i/2].type == UPTSet) &&
|
||||
(glob->pattern[i/2].content.Set.elements)) {
|
||||
for(elem = glob->pattern[i/2].content.Set.size - 1;
|
||||
if((glob->pattern[i].type == UPTSet) &&
|
||||
(glob->pattern[i].content.Set.elements)) {
|
||||
for(elem = glob->pattern[i].content.Set.size - 1;
|
||||
elem >= 0;
|
||||
--elem) {
|
||||
Curl_safefree(glob->pattern[i/2].content.Set.elements[elem]);
|
||||
}
|
||||
Curl_safefree(glob->pattern[i/2].content.Set.elements);
|
||||
Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
|
||||
}
|
||||
Curl_safefree(glob->pattern[i].content.Set.elements);
|
||||
}
|
||||
}
|
||||
Curl_safefree(glob->glob_buffer);
|
||||
@@ -426,7 +441,6 @@ void glob_cleanup(URLGlob* glob)
|
||||
int glob_next_url(char **globbed, URLGlob *glob)
|
||||
{
|
||||
URLPattern *pat;
|
||||
char *lit;
|
||||
size_t i;
|
||||
size_t j;
|
||||
size_t len;
|
||||
@@ -442,7 +456,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
|
||||
|
||||
/* implement a counter over the index ranges of all patterns,
|
||||
starting with the rightmost pattern */
|
||||
for(i = glob->size / 2 - 1; carry && (i < glob->size); --i) {
|
||||
for(i = glob->size - 1; carry && (i < glob->size); --i) {
|
||||
carry = FALSE;
|
||||
pat = &glob->pattern[i];
|
||||
switch (pat->type) {
|
||||
@@ -480,14 +494,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
|
||||
}
|
||||
|
||||
for(j = 0; j < glob->size; ++j) {
|
||||
if(!(j&1)) { /* every other term (j even) is a literal */
|
||||
lit = glob->literal[j/2];
|
||||
len = snprintf(buf, buflen, "%s", lit);
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
}
|
||||
else { /* the rest (i odd) are patterns */
|
||||
pat = &glob->pattern[j/2];
|
||||
pat = &glob->pattern[j];
|
||||
switch(pat->type) {
|
||||
case UPTSet:
|
||||
if(pat->content.Set.elements) {
|
||||
@@ -502,7 +509,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
|
||||
*buf++ = pat->content.CharRange.ptr_c;
|
||||
break;
|
||||
case UPTNumRange:
|
||||
len = snprintf(buf, buflen, "%0*d",
|
||||
len = snprintf(buf, buflen, "%0*ld",
|
||||
pat->content.NumRange.padlength,
|
||||
pat->content.NumRange.ptr_n);
|
||||
buf += len;
|
||||
@@ -513,7 +520,6 @@ int glob_next_url(char **globbed, URLGlob *glob)
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
|
||||
*globbed = strdup(glob->glob_buffer);
|
||||
@@ -549,34 +555,44 @@ int glob_match_url(char **result, char *filename, URLGlob *glob)
|
||||
unsigned long i;
|
||||
char *ptr = filename;
|
||||
unsigned long num = strtoul(&filename[1], &filename, 10);
|
||||
i = num - 1UL;
|
||||
URLPattern *pat =NULL;
|
||||
|
||||
if(num && (i <= glob->size / 2)) {
|
||||
URLPattern pat = glob->pattern[i];
|
||||
switch (pat.type) {
|
||||
if(num < glob->size) {
|
||||
num--; /* make it zero based */
|
||||
/* find the correct glob entry */
|
||||
for(i=0; i<glob->size; i++) {
|
||||
if(glob->pattern[i].globindex == (int)num) {
|
||||
pat = &glob->pattern[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pat) {
|
||||
switch (pat->type) {
|
||||
case UPTSet:
|
||||
if(pat.content.Set.elements) {
|
||||
appendthis = pat.content.Set.elements[pat.content.Set.ptr_s];
|
||||
if(pat->content.Set.elements) {
|
||||
appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
|
||||
appendlen =
|
||||
strlen(pat.content.Set.elements[pat.content.Set.ptr_s]);
|
||||
strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
|
||||
}
|
||||
break;
|
||||
case UPTCharRange:
|
||||
numbuf[0] = pat.content.CharRange.ptr_c;
|
||||
numbuf[0] = pat->content.CharRange.ptr_c;
|
||||
numbuf[1] = 0;
|
||||
appendthis = numbuf;
|
||||
appendlen = 1;
|
||||
break;
|
||||
case UPTNumRange:
|
||||
snprintf(numbuf, sizeof(numbuf), "%0*d",
|
||||
pat.content.NumRange.padlength,
|
||||
pat.content.NumRange.ptr_n);
|
||||
pat->content.NumRange.padlength,
|
||||
pat->content.NumRange.ptr_n);
|
||||
appendthis = numbuf;
|
||||
appendlen = strlen(numbuf);
|
||||
break;
|
||||
default:
|
||||
printf("internal error: invalid pattern type (%d)\n",
|
||||
(int)pat.type);
|
||||
fprintf(stderr, "internal error: invalid pattern type (%d)\n",
|
||||
(int)pat->type);
|
||||
Curl_safefree(target);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
@@ -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
|
||||
@@ -31,11 +31,13 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
URLPatternType type;
|
||||
int globindex; /* the number of this particular glob or -1 if not used
|
||||
within {} or [] */
|
||||
union {
|
||||
struct {
|
||||
char **elements;
|
||||
short size;
|
||||
short ptr_s;
|
||||
int size;
|
||||
int ptr_s;
|
||||
} Set;
|
||||
struct {
|
||||
char min_c;
|
||||
@@ -44,29 +46,29 @@ typedef struct {
|
||||
int step;
|
||||
} CharRange;
|
||||
struct {
|
||||
int min_n;
|
||||
int max_n;
|
||||
short padlength;
|
||||
int ptr_n;
|
||||
int step;
|
||||
unsigned long min_n;
|
||||
unsigned long max_n;
|
||||
int padlength;
|
||||
unsigned long ptr_n;
|
||||
unsigned long step;
|
||||
} NumRange ;
|
||||
} content;
|
||||
} URLPattern;
|
||||
|
||||
/* the total number of globs supported */
|
||||
#define GLOB_PATTERN_NUM 9
|
||||
#define GLOB_PATTERN_NUM 100
|
||||
|
||||
typedef struct {
|
||||
char *literal[10];
|
||||
URLPattern pattern[GLOB_PATTERN_NUM+1];
|
||||
URLPattern pattern[GLOB_PATTERN_NUM];
|
||||
size_t size;
|
||||
size_t urllen;
|
||||
char *glob_buffer;
|
||||
char beenhere;
|
||||
char errormsg[80]; /* error message buffer */
|
||||
const char *error; /* error message */
|
||||
size_t pos; /* column position of error or 0 */
|
||||
} URLGlob;
|
||||
|
||||
int glob_url(URLGlob**, char*, int *, FILE *);
|
||||
int glob_url(URLGlob**, char*, unsigned long *, FILE *);
|
||||
int glob_next_url(char **, URLGlob *);
|
||||
int glob_match_url(char **, char*, URLGlob *);
|
||||
void glob_cleanup(URLGlob* glob);
|
||||
|
@@ -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
|
||||
@@ -23,13 +23,18 @@
|
||||
|
||||
#ifdef HAVE_FSETXATTR
|
||||
# include <sys/xattr.h> /* header from libc, not from libattr */
|
||||
# define USE_XATTR
|
||||
#elif defined(__FreeBSD_version) && (__FreeBSD_version > 500000)
|
||||
# include <sys/types.h>
|
||||
# include <sys/extattr.h>
|
||||
# define USE_XATTR
|
||||
#endif
|
||||
|
||||
#include "tool_xattr.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
#ifdef HAVE_FSETXATTR
|
||||
#ifdef USE_XATTR
|
||||
|
||||
/* mapping table of curl metadata to extended attribute names */
|
||||
static const struct xattr_mapping {
|
||||
@@ -60,6 +65,12 @@ int fwrite_xattr(CURL *curl, int fd)
|
||||
err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
|
||||
#elif defined(HAVE_FSETXATTR_5)
|
||||
err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
|
||||
#elif defined(__FreeBSD_version)
|
||||
err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr, value,
|
||||
strlen(value));
|
||||
/* FreeBSD's extattr_set_fd returns the length of the extended attribute
|
||||
*/
|
||||
err = err < 0 ? err : 0;
|
||||
#endif
|
||||
}
|
||||
i++;
|
||||
|
@@ -125,6 +125,13 @@ SLOWDOWN
|
||||
- Send FTP responses with 0.01 sec delay between each byte
|
||||
PASVBADIP
|
||||
- makes PASV send back an illegal IP in its 227 response
|
||||
CAPA [capabilities]
|
||||
- Enables support for and specifies a list of space separated capabilities to
|
||||
return to the client for the IMAP CAPABILITY, POP3 CAPA and SMTP EHLO
|
||||
commands
|
||||
AUTH [mechanisms]
|
||||
- Enables support for SASL authentication and specifies a list of space
|
||||
separated mechanisms for IMAP, POP3 and SMTP
|
||||
|
||||
For HTTP/HTTPS:
|
||||
auth_required if this is set and a POST/PUT is made without auth, the
|
||||
@@ -144,6 +151,10 @@ rtp: part [num] channel [num] size [num]
|
||||
connection-monitor When used, this will log [DISCONNECT] to the server.input
|
||||
log when the connection is disconnected.
|
||||
|
||||
|
||||
For TFTP:
|
||||
writedelay: [secs] delay this amount between reply packets (each packet being
|
||||
512 bytes payload)
|
||||
</servercmd>
|
||||
</reply>
|
||||
|
||||
|
@@ -64,12 +64,14 @@ test700 test701 test702 test703 test704 test705 test706 test707 test708 \
|
||||
test709 test710 test711 test712 \
|
||||
\
|
||||
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
|
||||
test809 \
|
||||
test809 test810 test811 test812 test813 test814 \
|
||||
\
|
||||
test850 test851 test852 test853 test854 test855 test856 test857 \
|
||||
test850 test851 test852 test853 test854 test855 test856 test857 test858 \
|
||||
test859 test860 test861 test862 \
|
||||
\
|
||||
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
|
||||
test909 test910 test911 \
|
||||
test909 test910 test911 test912 test913 test914 test915 test916 test917 \
|
||||
test918 \
|
||||
\
|
||||
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
|
||||
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
||||
@@ -93,7 +95,8 @@ test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
|
||||
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
|
||||
test1216 test1217 test1218 test1219 \
|
||||
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
|
||||
test1228 test1229 test1230 test1231 test1232 test1233 \
|
||||
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
|
||||
test1236 test1237 test1238 test1239 \
|
||||
\
|
||||
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
|
||||
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
|
||||
@@ -110,7 +113,7 @@ test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1395 \
|
||||
test1396 \
|
||||
\
|
||||
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
|
||||
test1408 test1409 test1410 test1412 test1413 test1414 \
|
||||
test1408 test1409 test1410 test1412 test1413 test1414 test1415 \
|
||||
\
|
||||
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
|
||||
test1508 test1509 test1510 test1511 test1512 \
|
||||
|
@@ -89,7 +89,7 @@ ftps
|
||||
FTPS download with strict timeout and slow data transfer
|
||||
</name>
|
||||
<command timeout="1">
|
||||
-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 7
|
||||
-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 16
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
32
tests/data/test1234
Normal file
32
tests/data/test1234
Normal file
@@ -0,0 +1,32 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
{} list
|
||||
FAILURE
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
none
|
||||
</server>
|
||||
<name>
|
||||
abusing {}-globbing
|
||||
</name>
|
||||
<command>
|
||||
"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/{}{}{}{"
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
# 3 == CURLE_URL_MALFORMAT
|
||||
<errorcode>
|
||||
3
|
||||
</errorcode>
|
||||
</verify>
|
||||
</testcase>
|
94
tests/data/test1235
Normal file
94
tests/data/test1235
Normal file
@@ -0,0 +1,94 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
{} list
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<data1>
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 15
|
||||
|
||||
the number one
|
||||
</data1>
|
||||
<data2>
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 16
|
||||
|
||||
two is nice too
|
||||
</data2>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
multiple requests using {}{} in the URL
|
||||
</name>
|
||||
<command>
|
||||
"%HOSTIP:%HTTPPORT/{1235,1235}{0001,0002}"
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /12350001 HTTP/1.1
|
||||
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /12350002 HTTP/1.1
|
||||
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /12350001 HTTP/1.1
|
||||
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /12350002 HTTP/1.1
|
||||
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
<stdout>
|
||||
--_curl_--%HOSTIP:%HTTPPORT/12350001
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 15
|
||||
|
||||
the number one
|
||||
--_curl_--%HOSTIP:%HTTPPORT/12350002
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 16
|
||||
|
||||
two is nice too
|
||||
--_curl_--%HOSTIP:%HTTPPORT/12350001
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 15
|
||||
|
||||
the number one
|
||||
--_curl_--%HOSTIP:%HTTPPORT/12350002
|
||||
HTTP/1.1 200 OK
|
||||
Funny-head: yesyes
|
||||
Content-Length: 16
|
||||
|
||||
two is nice too
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
33
tests/data/test1236
Normal file
33
tests/data/test1236
Normal file
@@ -0,0 +1,33 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
globbing
|
||||
FAILURE
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
none
|
||||
</server>
|
||||
<name>
|
||||
[] globbing overflowing the range counter
|
||||
</name>
|
||||
# 2^62 == 4611686018427387904
|
||||
<command>
|
||||
"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/[1-4611686018427387904][1-4611686018427387904]"
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
# 3 == CURLE_URL_MALFORMAT
|
||||
<errorcode>
|
||||
3
|
||||
</errorcode>
|
||||
</verify>
|
||||
</testcase>
|
47
tests/data/test1237
Normal file
47
tests/data/test1237
Normal file
@@ -0,0 +1,47 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
Basic
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 OK
|
||||
Server: test-server/fake
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
URL with 1000+ letter user name + password
|
||||
</name>
|
||||
<command>
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@%HOSTIP:%HTTPPORT/1237"
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /1237 HTTP/1.1
|
||||
Authorization: Basic QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQTpCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI=
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
49
tests/data/test1238
Normal file
49
tests/data/test1238
Normal file
@@ -0,0 +1,49 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
TFTP
|
||||
TFTP RRQ
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<servercmd>
|
||||
writedelay: 1
|
||||
</servercmd>
|
||||
# ~1200 bytes (so that they don't fit in two 512 byte chunks)
|
||||
<data nocheck="yes">
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
tftp
|
||||
</server>
|
||||
<name>
|
||||
slow TFTP retrieve cancel due to -Y and -y
|
||||
</name>
|
||||
# if less than 1000 bytes/sec within 2 seconds, abort!
|
||||
<command>
|
||||
tftp://%HOSTIP:%TFTPPORT//1238 -Y1000 -y2
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify pseudo protocol after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
opcode: 1
|
||||
filename: /1238
|
||||
mode: octet
|
||||
</protocol>
|
||||
# 28 = CURLE_OPERATION_TIMEDOUT
|
||||
<errorcode>
|
||||
28
|
||||
</errorcode>
|
||||
</verify>
|
||||
</testcase>
|
68
tests/data/test1239
Normal file
68
tests/data/test1239
Normal file
@@ -0,0 +1,68 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
-z
|
||||
</keywords>
|
||||
</info>
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data nocheck="yes">
|
||||
HTTP/1.1 200 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2010 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP with -z + -w response_code and simulated 304
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/1239 -z "-dec 12 12:00:00 1999 GMT" -w '%{response_code}'
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /1239 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
If-Unmodified-Since: Sun, 12 Dec 1999 12:00:00 GMT
|
||||
|
||||
</protocol>
|
||||
<stdout nonewline="yes">
|
||||
HTTP/1.1 200 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2010 12:10:00 GMT
|
||||
ETag: "21025-dc7-39462498"
|
||||
Accept-Ranges: bytes
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
304
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
@@ -35,7 +35,7 @@ To: another
|
||||
body
|
||||
</stdin>
|
||||
<command>
|
||||
smtp://smtp.1320:%SMTPPORT/user --mail-rcpt 1320@foo --mail-rcpt 1320@foobar.example --mail-from 1320@from -T - -p -x %HOSTIP:%PROXYPORT
|
||||
smtp://smtp.1320:%SMTPPORT/1320 --mail-rcpt recipient@example.com --mail-from sender@example.com -T - -p -x %HOSTIP:%PROXYPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
@@ -46,10 +46,9 @@ smtp://smtp.1320:%SMTPPORT/user --mail-rcpt 1320@foo --mail-rcpt 1320@foobar.exa
|
||||
^User-Agent: curl/.*
|
||||
</strip>
|
||||
<protocol>
|
||||
EHLO user
|
||||
MAIL FROM:<1320@from>
|
||||
RCPT TO:<1320@foo>
|
||||
RCPT TO:<1320@foobar.example>
|
||||
EHLO 1320
|
||||
MAIL FROM:<sender@example.com>
|
||||
RCPT TO:<recipient@example.com>
|
||||
DATA
|
||||
QUIT
|
||||
</protocol>
|
||||
|
@@ -11,6 +11,9 @@ SMTP
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<servercmd>
|
||||
CAPA SIZE
|
||||
</servercmd>
|
||||
</reply>
|
||||
|
||||
#
|
||||
@@ -29,7 +32,7 @@ To: another
|
||||
body
|
||||
</file>
|
||||
<command>
|
||||
smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.example --mail-from 1406@from -T log/test1406.eml --libcurl log/test1406.c
|
||||
smtp://%HOSTIP:%SMTPPORT/1406 --mail-rcpt recipient.one@example.com --mail-rcpt recipient.two@example.com --mail-from sender@example.com -T log/test1406.eml --libcurl log/test1406.c
|
||||
</command>
|
||||
</client>
|
||||
|
||||
@@ -37,10 +40,10 @@ smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.examp
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
EHLO user
|
||||
MAIL FROM:<1406@from> SIZE=38
|
||||
RCPT TO:<1406@foo>
|
||||
RCPT TO:<1406@foobar.example>
|
||||
EHLO 1406
|
||||
MAIL FROM:<sender@example.com> SIZE=38
|
||||
RCPT TO:<recipient.one@example.com>
|
||||
RCPT TO:<recipient.two@example.com>
|
||||
DATA
|
||||
QUIT
|
||||
</protocol>
|
||||
@@ -65,19 +68,19 @@ int main(int argc, char *argv[])
|
||||
struct curl_slist *slist1;
|
||||
|
||||
slist1 = NULL;
|
||||
slist1 = curl_slist_append(slist1, "1406@foo");
|
||||
slist1 = curl_slist_append(slist1, "1406@foobar.example");
|
||||
slist1 = curl_slist_append(slist1, "recipient.one@example.com");
|
||||
slist1 = curl_slist_append(slist1, "recipient.two@example.com");
|
||||
|
||||
hnd = curl_easy_init();
|
||||
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)38);
|
||||
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/user");
|
||||
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406");
|
||||
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
|
||||
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
|
||||
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "1406@from");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com");
|
||||
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1);
|
||||
|
||||
/* Here is a list of options the curl code used that cannot get generated
|
||||
|
72
tests/data/test1415
Normal file
72
tests/data/test1415
Normal file
@@ -0,0 +1,72 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
cookies
|
||||
cookiejar
|
||||
delete expired cookie
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Content-Length: 4
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
Set-Cookie: test1value=test1; domain=example.com; path=/;
|
||||
Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
|
||||
Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
|
||||
|
||||
boo
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
Delete expired cookies
|
||||
</name>
|
||||
<setenv>
|
||||
TZ=GMT
|
||||
</setenv>
|
||||
<command>
|
||||
http://example.com/we/want/1415 -b none -c log/jar1415.txt -x %HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET http://example.com/we/want/1415 HTTP/1.1
|
||||
Host: example.com
|
||||
Accept: */*
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
</protocol>
|
||||
|
||||
<file name="log/jar1415.txt" mode="text">
|
||||
# Netscape HTTP Cookie File
|
||||
# http://curl.haxx.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
.example.com TRUE / FALSE 0 test1value test1
|
||||
.example.com TRUE / FALSE 2114380800 test2value test2
|
||||
.example.com TRUE / FALSE 2114380800 test4value test4
|
||||
.example.com TRUE / FALSE 2114380800 test7value test7
|
||||
</file>
|
||||
</verify>
|
||||
</testcase>
|
@@ -32,7 +32,7 @@ To: another
|
||||
body
|
||||
</stdin>
|
||||
<command>
|
||||
smtp://%HOSTIP:%SMTPPORT/user
|
||||
smtp://%HOSTIP:%SMTPPORT/1507
|
||||
</command>
|
||||
</client>
|
||||
|
||||
@@ -40,7 +40,7 @@ smtp://%HOSTIP:%SMTPPORT/user
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
EHLO user
|
||||
EHLO 1507
|
||||
MAIL FROM:<1507-realuser@example.com>
|
||||
RCPT TO:<1507-recipient@example.com>
|
||||
DATA
|
||||
|
@@ -123,22 +123,22 @@ chkhostname curlhost
|
||||
<protocol>
|
||||
GET /20320100 HTTP/1.1
|
||||
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320100 HTTP/1.1
|
||||
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320200 HTTP/1.1
|
||||
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320200 HTTP/1.1
|
||||
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
|
@@ -124,22 +124,22 @@ chkhostname curlhost
|
||||
<protocol>
|
||||
GET /20320100 HTTP/1.1
|
||||
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320100 HTTP/1.1
|
||||
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320200 HTTP/1.1
|
||||
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /20320200 HTTP/1.1
|
||||
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q=
|
||||
Host: 127.0.0.1:8990
|
||||
Host: 127.0.0.1:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user