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 |  Public curl releases:         135 | ||||||
|  Command line options:         152 |  Command line options:         161 | ||||||
|  curl_easy_setopt() options:   199 |  curl_easy_setopt() options:   205 | ||||||
|  Public functions in libcurl:  58 |  Public functions in libcurl:  58 | ||||||
|  Known libcurl bindings:       42 |  Known libcurl bindings:       42 | ||||||
|  Contributors:                 1049 |  Contributors:                 1057 | ||||||
|  |  | ||||||
| *** |  | ||||||
|   krb4 support is up for removal. If you care about it at all, speak up |  | ||||||
|   on the curl-library list asap! |  | ||||||
| *** |  | ||||||
|  |  | ||||||
| This release includes the following changes: | This release includes the following changes: | ||||||
|  |  | ||||||
|  o curl: allow timeouts to accept decimal values |  o test code for testing the event based API [3] | ||||||
|  o OS400: add slist and certinfo EBCDIC support |  o CURLM_ADDED_ALREADY: new error code | ||||||
|  o OS400: new SSL backend GSKit |  o test TFTP server: support "writedelay" within <servercmd> | ||||||
|  o CURLOPT_XFERINFOFUNCTION: introducing a new progress callback |  o krb4 support has been removed | ||||||
|  o LIBCURL-STRUCTS: new document |  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: | This release includes the following bugfixes: | ||||||
|  |  | ||||||
|  o dotdot: introducing dot file path cleanup [1] |  o nss: make sure that NSS is initialized | ||||||
|  o docs: fix typo in curl_easy_getinfo manpage |  o curl: make --no-[option] work properly for several options | ||||||
|  o test1230: avoid using hard-wired port number |  o FTP: with socket_action send better socket updates in active mode [1] | ||||||
|  o test1396: invoke the correct test tool |  o curl: fix the --sasl-ir in the --help output | ||||||
|  o SIGPIPE: ignored while inside the library [2] |  o tests 2032, 2033: Don't hardcode port in expected output | ||||||
|  o darwinssl: fix crash that started happening in Lion |  o urlglob: better detect unclosed braces, empty lists and overflows [7] | ||||||
|  o OpenSSL: check for read errors, don't assume [3] |  o urlglob: error out on range overflow [8] | ||||||
|  o c-ares: improve error message on failed resolve [4] |  o imap: Fixed response check for SEARCH, EXPUNGE, LSUB, UID and NOOP commands [10] | ||||||
|  o printf: make sure %x are treated unsigned |  o handle arbitrary-length username and password [2] | ||||||
|  o formpost: better random boundaries [5] |  o TFTP: make the CURLOPT_LOW_SPEED* options work [4] | ||||||
|  o url: restore the functionality of 'curl -u :' [6] |  o curl.h: name space pollution by "enum type" [5] | ||||||
|  o curl.1: fix typo in --xattr description [7] |  o multi: move on from STATE_DONE faster [6] | ||||||
|  o digest: improve nonce generation |  o FTP: 60 secs delay if aborted in the CURLOPT_HEADERFUNCTION callback [11] | ||||||
|  o configure: automake 1.14 compatibility tweak |  o multi_socket: improved 100-continue timeout handling | ||||||
|  o curl.1: document the --post303 option in the man page |  o curl_multi_remove_handle: allow multiple removes | ||||||
|  o curl.1: document the --sasl-ir option in the man page |  o FTP: fix getsock during DO_MORE state [12] | ||||||
|  o setup-vms.h: sk_pop symbol tweak |  o -x: rephrased the --proxy section somewhat | ||||||
|  o tool_paramhlp: try harder to catch negatives |  o acinclude: fix --without-ca-path when cross-compiling [13] | ||||||
|  o cmake: Fix for MSVC2010 project generation [8] |  o LDAP: fix bad free() when URL parsing failed [14] | ||||||
|  o asyn-ares: Don't blank ares servers if none configured |  o --data: mention CRLF treatment when reading from file | ||||||
|  o curl_multi_wait: set revents for extra fds |  o curl_easy_pause: suggest one way to unpause | ||||||
|  o Reinstate "WIN32 MemoryTracking: track wcsdup() _wcsdup() and _tcsdup() |  o imap: Fixed calculation of transfer when partial FETCH received [16] | ||||||
|  o ftp_do_more: consider DO_MORE complete when server connects back [9] |  o pingpong: Check SSL library buffers for already read data [16] | ||||||
|  o curl_easy_perform: gradually increase the delay time [10] |  o imap/pop3/smtp: Speed up SSL connection initialization | ||||||
|  o curl: fix symbolic names for CURLUSESSL_* enum in --libcurl output |  o libcurl.3: for multi interface connections are held in the multi handle | ||||||
|  o curl: fix upload of a zip file in OpenVMS [11] |  o curl_easy_setopt.3: mention RTMP URL quirks [17] | ||||||
|  o build: fix linking on Solaris 10 [12] |  o curl.1: detail how short/long options work [18] | ||||||
|  o curl_formadd: CURLFORM_FILECONTENT wrongly rejected some option combos [13] |  o curl.1: Added information about optional login options to --user option | ||||||
|  o curl_formadd: fix file upload on VMS [14] |  o curl: Added clarification to the --mail options in the --help output | ||||||
|  o curl_easy_pause: on unpause, trigger mulit-socket handling [15] |  o curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value | ||||||
|  o md5 & metalink: use better build macros on Apple operating systems [16] |  o openssl: use correct port number in error message [19] | ||||||
|  o darwinssl: fix build error in crypto authentication under Snow Leopard [16] |  o darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher | ||||||
|  o curl: make --progress-bar update the line less frequently [17] |  o OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER | ||||||
|  o configure: don't error out on variable confusions (CFLAGS, LDFLAGS etc) |  o xattr: add support for FreeBSD xattr API | ||||||
|  o mk-ca-bundle: skip more untrusted certificates |  o win32: fix Visual Studio 2010 build with WINVER >= 0x600 [22] | ||||||
|  o formadd: wrong pointer for file name when CURLFORM_BUFFERPTR used [18] |  o configure: use icc options without space [21] | ||||||
|  o FTP: when EPSV gets a 229 but fails to connect, retry with PASV |  o test1112: Increase the timeout from 7s to 16s [20] | ||||||
|  o mk-ca-bundle.1: don't install on make install [19] |  o SCP: upload speed on a fast connection limited to 16384 B/s | ||||||
|  o VMS: lots of updates and fixes of the build procedure |  o curl_setup_once: fix errno access for lwip on Windows [24] | ||||||
|  o global dns cache: didn't work (regression) |  o HTTP: Output http response 304 when modified time is too old [23] | ||||||
|  o global dns cache: fix memory leak |  | ||||||
|  o  |  | ||||||
|  |  | ||||||
| This release includes the following known bugs: | 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 | This release would not have looked like this without help, code, reports and | ||||||
| advice from friends like these: | advice from friends like these: | ||||||
|  |  | ||||||
|  Alex Vinnik, Alessandro Ghedini, Nick Zitzmann, Kamil Dudka, |  Alex McLellan, Bill Doyle, Colby Ranger, Fabian Keil, Gisle Vanem, | ||||||
|  Lluis Batlle i Rossell, Nach M. S., Kim Vandry, Ben Greear, Dan Fandrich, |  John E. Malmberg, Jonathan Nieder, Kamil Dudka, Shawn Landden, | ||||||
|  Dave Reisner, Evgeny Turnaev, Guenter Knauf, John E. Malmberg, Marc Hoersken, |  Tor Arntsen, Will Dietz, Yi Huang, Kyle L. Huff, Steve Holme, Mike Mio, | ||||||
|  Patrick Monnerat, Sergei Nikulov, Yang Tse, Andreas Malzahn, Clemens Gruber, |  Stefan Neis, Nick Zitzmann, Geoff Beier, John Dunn, Jiri Hruska, | ||||||
|  Jean-Noel Rouvignac, Markus Moeller, Fabian Keil, Dagobert Michelsen, |  Tomas Mlcoch, Kim Vandry, Ben Greear, Gorilla Maguila, Jerry Krinock, | ||||||
|  Byrial Jensen, Justin Karneges, Edward Rudd, Marc Doughty, Konstantin Isakov, |  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) |         Thanks! (and sorry if I forgot to mention someone) | ||||||
|  |  | ||||||
| References to bug reports and discussions on issues: | References to bug reports and discussions on issues: | ||||||
|  |  | ||||||
|  [1] = http://curl.haxx.se/bug/view.cgi?id=1200 |  [1] = http://curl.haxx.se/mail/lib-2013-08/0043.html | ||||||
|  [2] = http://curl.haxx.se/bug/view.cgi?id=1180 |  [2] = http://bugs.debian.org/719856 | ||||||
|  [3] = http://curl.haxx.se/bug/view.cgi?id=1249 |  [3] = http://daniel.haxx.se/blog/2013/08/20/testing-curl_multi_socket_action/ | ||||||
|  [4] = http://curl.haxx.se/bug/view.cgi?id=1191 |  [4] = http://curl.haxx.se/bug/view.cgi?id=1269 | ||||||
|  [5] = http://curl.haxx.se/bug/view.cgi?id=1251 |  [5] = https://github.com/bagder/curl/pull/76 | ||||||
|  [6] = http://curl.haxx.se/mail/archive-2013-06/0052.html |  [6] = http://curl.haxx.se/mail/lib-2013-08/0211.html | ||||||
|  [7] = http://curl.haxx.se/bug/view.cgi?id=1252 |  [7] = http://curl.haxx.se/bug/view.cgi?id=1264 | ||||||
|  [8] = http://curl.haxx.se/mail/lib-2013-07/0046.html |  [8] = http://curl.haxx.se/bug/view.cgi?id=1267 | ||||||
|  [9] = http://curl.haxx.se/mail/lib-2013-07/0115.html |  [9] = http://curl.haxx.se/mail/lib-2013-08/0234.html | ||||||
|  [10] = http://curl.haxx.se/mail/lib-2013-07/0103.html |  [10] = http://curl.haxx.se/mail/lib-2013-08/0136.html | ||||||
|  [11] = http://curl.haxx.se/bug/view.cgi?id=496 |  [11] = https://bugzilla.redhat.com/1005686 | ||||||
|  [12] = http://curl.haxx.se/bug/view.cgi?id=1217 |  [12] = http://curl.haxx.se/mail/lib-2013-08/0109.html | ||||||
|  [13] = http://curl.haxx.se/mail/lib-2013-07/0258.html |  [13] = http://curl.haxx.se/bug/view.cgi?id=1273 | ||||||
|  [14] = http://curl.haxx.se/bug/view.cgi?id=758 |  [14] = http://curl.haxx.se/mail/lib-2013-08/0209.html | ||||||
|  [15] = http://curl.haxx.se/mail/lib-2013-07/0239.html |  [15] = http://curl.haxx.se/mail/lib-2013-08/0265.html | ||||||
|  [16] = http://curl.haxx.se/bug/view.cgi?id=1255 |  [16] = http://curl.haxx.se/mail/lib-2013-08/0170.html | ||||||
|  [17] = http://curl.haxx.se/mail/archive-2013-07/0031.html |  [17] = http://curl.haxx.se/bug/view.cgi?id=1278 | ||||||
|  [18] = http://curl.haxx.se/bug/view.cgi?id=1262 |  [18] = http://curl.haxx.se/bug/view.cgi?id=1279 | ||||||
|  [19] = http://curl.haxx.se/mail/lib-2013-08/0057.html |  [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 |     fi | ||||||
|     capath="$want_capath" |     capath="$want_capath" | ||||||
|     ca="no" |     ca="no" | ||||||
|   elif test "x$cross_compiling" != "xyes"; then |   else | ||||||
|     dnl NOT cross-compiling and... |  | ||||||
|     dnl neither of the --with-ca-* options are provided |  | ||||||
|  |  | ||||||
|     dnl first try autodetecting a CA bundle , then a CA path |     dnl first try autodetecting a CA bundle , then a CA path | ||||||
|     dnl both autodetections can be skipped by --without-ca-* |     dnl both autodetections can be skipped by --without-ca-* | ||||||
|     ca="no" |     ca="no" | ||||||
|     capath="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 |       if test "x$want_ca" = "xunset"; then | ||||||
|         dnl the path we previously would have installed the curl ca bundle |         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 to, and thus we now check for an already existing cert in that | ||||||
|       dnl in case we find no other |         dnl place in case we find no other | ||||||
|         if test "x$prefix" != xNONE; then |         if test "x$prefix" != xNONE; then | ||||||
|           cac="${prefix}/share/curl/curl-ca-bundle.crt" |           cac="${prefix}/share/curl/curl-ca-bundle.crt" | ||||||
|         else |         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 |       dnl no option given and cross-compiling | ||||||
|       AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling]) |       AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling]) | ||||||
|     fi |     fi | ||||||
|  |   fi | ||||||
|  |  | ||||||
|   if test "x$ca" != "xno"; then |   if test "x$ca" != "xno"; then | ||||||
|     CURL_CA_BUNDLE='"'$ca'"' |     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_ssl_msg="no      (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )" | ||||||
|     curl_ssh_msg="no      (--with-libssh2)" |     curl_ssh_msg="no      (--with-libssh2)" | ||||||
|    curl_zlib_msg="no      (--with-zlib)" |    curl_zlib_msg="no      (--with-zlib)" | ||||||
|    curl_krb4_msg="no      (--with-krb4*)" |  | ||||||
|     curl_gss_msg="no      (--with-gssapi)" |     curl_gss_msg="no      (--with-gssapi)" | ||||||
|  curl_spnego_msg="no      (--with-spnego)" |  curl_spnego_msg="no      (--with-spnego)" | ||||||
| curl_tls_srp_msg="no      (--enable-tls-srp)" | curl_tls_srp_msg="no      (--enable-tls-srp)" | ||||||
| @@ -1134,101 +1133,6 @@ no) | |||||||
|         ;; |         ;; | ||||||
| esac | 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 ********************************************************************** | ||||||
| dnl Check for FBopenssl(SPNEGO) libraries | dnl Check for FBopenssl(SPNEGO) libraries | ||||||
| dnl ********************************************************************** | 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 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 ********************************************************************** | ||||||
| dnl Back to "normal" configuring | dnl Back to "normal" configuring | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| @@ -3365,9 +3355,6 @@ if test "x$USE_SSLEAY" = "x1"; then | |||||||
| elif test -n "$SSL_ENABLED"; then | elif test -n "$SSL_ENABLED"; then | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" |   SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" | ||||||
| fi | fi | ||||||
| if test "@KRB4_ENABLED@" = "x1"; then |  | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4" |  | ||||||
| fi |  | ||||||
| if test "x$IPV6_ENABLED" = "x1"; then | if test "x$IPV6_ENABLED" = "x1"; then | ||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" |   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" | ||||||
| fi | fi | ||||||
| @@ -3397,6 +3384,10 @@ if test "x$USE_TLS_SRP" = "x1"; then | |||||||
|   SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" |   SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" | ||||||
| fi | fi | ||||||
|  |  | ||||||
|  | if test "x$USE_NGHTTP2" = "x1"; then | ||||||
|  |   SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2" | ||||||
|  | fi | ||||||
|  |  | ||||||
| AC_SUBST(SUPPORT_FEATURES) | AC_SUBST(SUPPORT_FEATURES) | ||||||
|  |  | ||||||
| dnl For supported protocols in pkg-config file | 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} |   SSL support:      ${curl_ssl_msg} | ||||||
|   SSH support:      ${curl_ssh_msg} |   SSH support:      ${curl_ssh_msg} | ||||||
|   zlib support:     ${curl_zlib_msg} |   zlib support:     ${curl_zlib_msg} | ||||||
|   krb4 support:     ${curl_krb4_msg} |  | ||||||
|   GSSAPI support:   ${curl_gss_msg} |   GSSAPI support:   ${curl_gss_msg} | ||||||
|   SPNEGO support:   ${curl_spnego_msg} |   SPNEGO support:   ${curl_spnego_msg} | ||||||
|   TLS-SRP support:  ${curl_tls_srp_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} |   RTSP support:     ${curl_rtsp_msg} | ||||||
|   RTMP support:     ${curl_rtmp_msg} |   RTMP support:     ${curl_rtmp_msg} | ||||||
|   metalink support: ${curl_mtlnk_msg} |   metalink support: ${curl_mtlnk_msg} | ||||||
|  |   HTTP2 support:    ${curl_h2_msg} | ||||||
|   Protocols:        ${SUPPORT_PROTOCOLS} |   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 |   better. We do however believe in a few rules when it comes to the future of | ||||||
|   curl: |   curl: | ||||||
|  |  | ||||||
|   * Curl -- the command line tool -- is to remain a non-graphical command line |   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 |   tool. If you want GUIs or fancy scripting capabilities, you should look for | ||||||
|     for another tool that uses libcurl. |   another tool that uses libcurl. | ||||||
|  |  | ||||||
|   * We do not add things to curl that other small and available tools already |   We do not add things to curl that other small and available tools already do | ||||||
|     do very fine at the side. Curl's output is fine to pipe into another |   very fine at the side. Curl's output is fine to pipe into another program or | ||||||
|     program or redirect to another file for the next program to interpret. |   redirect to another file for the next program to interpret. | ||||||
|  |  | ||||||
|   * We focus on protocol related issues and improvements. If you wanna do more |   We focus on protocol related issues and improvements. If you wanna do more | ||||||
|     magic with the supported protocols than curl currently does, chances are |   magic with the supported protocols than curl currently does, chances are big | ||||||
|     big we will agree. If you wanna add more protocols, we may very well |   we will agree. If you wanna add more protocols, we may very well agree. | ||||||
|     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 |   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 |   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 |   get more out of us, you should consider trading in some of your time and | ||||||
|   efforts in return. |   efforts in return. | ||||||
|  |  | ||||||
|   * If you write the code, chances are bigger that it will get into curl |   If you write the code, chances are bigger that it will get into curl faster. | ||||||
|     faster. |  | ||||||
|  |  | ||||||
|   1.5 Who makes curl? |   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 |   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 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 |   We recognize that we will be living in parallel with curl.com and wish them | ||||||
|   every success. |   every success. | ||||||
| @@ -620,15 +618,15 @@ FAQ | |||||||
|  |  | ||||||
|   Some workarounds usually suggested to overcome this Javascript dependency: |   Some workarounds usually suggested to overcome this Javascript dependency: | ||||||
|  |  | ||||||
|   - Depending on the Javascript complexity, write up a script that |   Depending on the Javascript complexity, write up a script that translates it | ||||||
|     translates it to another language and execute that. |   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. |   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? |   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 |   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. |   talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. | ||||||
|  |  | ||||||
|   - Client certificate. The server you communicate may require that you can |   CLIENT CERTIFICATE | ||||||
|     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. |   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 |   A client certificate is always used together with a private key, and the | ||||||
|   private key has a pass phrase that protects it. |   private key has a pass phrase that protects it. | ||||||
|  |  | ||||||
|   - Server certificate. The server you communicate with has a server |   SERVER CERTIFICATE | ||||||
|     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 |   The server you communicate with has a server certificate. You can and should | ||||||
|     certs in a CA cert bundle that can be used to verify a server certificate |   verify this certificate to make sure that you are truly talking to the real | ||||||
|     that was signed by one of the authorities in the bundle. curl does not |   server and not a server impersonating it. | ||||||
|     come with a CA cert bundle but most curl installs provide one. You can |  | ||||||
|     also override the default. |   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 |   The server certificate verification process is made by using a Certificate | ||||||
|   Authority certificate ("CA cert") that was used to sign the server |   Authority certificate ("CA cert") that was used to sign the server | ||||||
| @@ -669,9 +671,9 @@ FAQ | |||||||
|   4.12 and the SSLCERTS document |   4.12 and the SSLCERTS document | ||||||
|   (http://curl.haxx.se/docs/sslcerts.html). Server certificates that are |   (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 |   "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 |   for, cannot be verified. If the verification during a connect fails, you are | ||||||
|     are refused access. You then need to explicitly disable the verification |   refused access. You then need to explicitly disable the verification to | ||||||
|     to connect to the server. |   connect to the server. | ||||||
|  |  | ||||||
|   3.17 How do I list the root dir of an FTP 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' |      curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl' | ||||||
|  |  | ||||||
|   In Windows, the standard DOS shell treats the %-symbol specially and you |   In Windows, the standard DOS shell treats the percent sign specially and you | ||||||
|   need to use TWO %-symbols for each single one you want to use in the URL. |   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 |   If you want a literal percent sign to be part of the data you pass in a POST | ||||||
|   pass in a POST using -d/--data you must encode it as '%25' (which then also |   using -d/--data you must encode it as '%25' (which then also needs the | ||||||
|   needs the %-symbol doubled on Windows machines). |   percent sign doubled on Windows machines). | ||||||
|  |  | ||||||
|   4.3 How can I use {, }, [ or ] to specify multiple URLs? |   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! |   4.14 Redirects work in browser but not with curl! | ||||||
|  |  | ||||||
|   curl supports HTTP redirects fine (see item 3.8). Browsers generally support |   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 |   Meta tags. You can write a HTML tag that will cause the browser to redirect | ||||||
|     redirect to another given URL after a certain time. |   to another given URL after a certain time. | ||||||
|  |  | ||||||
|   - Javascript. You can write a Javascript program embedded in a HTML page |   Javascript. You can write a Javascript program embedded in a HTML page that | ||||||
|     that redirects the browser to another given URL. |   redirects the browser to another given URL. | ||||||
|  |  | ||||||
|   There is no way to make curl follow these redirects. You must either |   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 |   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? |   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 |   No. libcurl operates on a higher level. Besides, faking IP address would | ||||||
|   would imply sending IP packages with a made-up source address, and then you |   imply sending IP packet with a made-up source address, and then you normally | ||||||
|   normally get a problem with intercepting the packages sent back as they |   get a problem with receiving the packet sent back as they would then not be | ||||||
|   would then not be routed to you! |   routed to you! | ||||||
|  |  | ||||||
|   If you use a proxy to access remote sites, the sites will not see your local |   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. |   IP address but instead the address of the proxy. | ||||||
|  |  | ||||||
|   Also note that on many networks NATs or other IP-munging techniques are used |   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 |   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? |   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 | changelog of the current development status, as one or more of these problems | ||||||
| may have been fixed since this was written! | 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 | 83. curl is unable to load non-default openssl engines, because openssl isn't | ||||||
|   initialized properly. This seems to require OpenSSL_config() or |   initialized properly. This seems to require OpenSSL_config() or | ||||||
|   CONF_modules_load_file() to be used by libcurl but the first seems to not |   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 | 80. Curl doesn't recognize certificates in DER format in keychain, but it | ||||||
|   works with PEM. |   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 | 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" |   failure if one of the recipients indicate failure (on the "RCPT TO" | ||||||
|   command). Ordinary mail programs would proceed and still send to the ones |   command). Ordinary mail programs would proceed and still send to the ones | ||||||
|   that can receive data. This is subject for change in the future. |   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" | 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 |   zero bytes files - it makes for example the command line client not creating | ||||||
|   any file at all. Like when using FTP. |   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 | 77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it | ||||||
|   "abuses" the underlying connection re-use system and if connections are |   "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 |   properly if built with UNICODE defined together with the schannel/winssl | ||||||
|   backend. The original problem was mentioned in: |   backend. The original problem was mentioned in: | ||||||
|   http://curl.haxx.se/mail/lib-2009-10/0024.html |   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 |   The schannel version verified to work as mentioned in | ||||||
|   http://curl.haxx.se/mail/lib-2012-07/0073.html |   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" |   acknowledge the connection timeout during that phase but only the "real" | ||||||
|   timeout - which may surprise users as it is probably considered to be the |   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: |   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." | 72. "Pausing pipeline problems." | ||||||
|   http://curl.haxx.se/mail/lib-2009-07/0214.html |   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 |   http://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02 | ||||||
|  |  | ||||||
| 66. When using telnet, the time limitation options don't work. | 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 | 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 |   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) |   and instead the connection is "cancelled" (the operation is considered done) | ||||||
|   prematurely. There is a half-baked (busy-looping) patch provided in the bug |   prematurely. There is a half-baked (busy-looping) patch provided in the bug | ||||||
|   report but it cannot be accepted as-is. See |   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 | 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 |   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. |   protocol code. This should be very rare. | ||||||
|  |  | ||||||
| 43. There seems to be a problem when connecting to the Microsoft telnet server. | 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 | 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 |   when logging in), the operation will fail since libcurl doesn't detect this | ||||||
|   and thus fails to issue the correct command: |   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: | 39. Steffen Rumler's Race Condition in Curl_proxyCONNECT: | ||||||
|   http://curl.haxx.se/mail/lib-2007-01/0045.html |   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. | 34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts. | ||||||
|   Also see #12. According to bug #1556528, even the SOCKS5 connect code does |   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 | 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 |   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 |   IDs in URLs to get around the problem of percent signs being | ||||||
|   special. According to the reporter, Firefox deals with the URL _with_ a |   special. According to the reporter, Firefox deals with the URL _with_ a | ||||||
|   percent letter (which seems like a blatant URL spec violation). |   percent letter (which seems like a blatant URL spec violation). | ||||||
|   libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25). |   libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25): | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=555 | ||||||
|    See http://curl.haxx.se/bug/view.cgi?id=1371118 |  | ||||||
|  |  | ||||||
| 26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in | 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 |   "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: | 23. SOCKS-related problems: | ||||||
|   B) libcurl doesn't support FTPS over a SOCKS proxy. |   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 | 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 |   (fake) user name (this concerns both curl and the lib) because the code | ||||||
|   wrongly only considers authentication if there's a user name provided. |   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 |   http://curl.haxx.se/mail/lib-2004-08/0182.html | ||||||
|  |  | ||||||
| 8. Doing resumed upload over HTTP does not work with '-C -', because curl | 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 | If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your | ||||||
| friend. | friend. | ||||||
| .SH OPTIONS | .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 | 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 | 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 | 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, | Make curl display progress as a simple progress bar instead of the standard, | ||||||
| more informational, meter. | more informational, meter. | ||||||
| .IP "-0, --http1.0" | .IP "-0, --http1.0" | ||||||
| (HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its | (HTTP) Tells curl to use HTTP version 1.0 instead of using its internally | ||||||
| internally preferred: HTTP 1.1. | 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" | .IP "-1, --tlsv1" | ||||||
| (SSL) | (SSL) | ||||||
| Forces curl to use TLS version 1 when negotiating with a remote TLS server. | 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 | 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 | 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 | 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>" | .IP "-D, --dump-header <file>" | ||||||
| Write the protocol headers to the specified 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 | 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 | 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 | If this option is used several times, the ones following the first will append | ||||||
| data as described in \fI-d, --data\fP. | 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 | Disabling EPSV only changes the passive behavior. If you want to switch to | ||||||
| active mode you need to use \fI-P, --ftp-port\fP. | 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>" | .IP "-e, --referer <URL>" | ||||||
| (HTTP) Sends the "Referer Page" information to the HTTP server. This can also | (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 | 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]>" | .IP "-E, --cert <certificate[:password]>" | ||||||
| (SSL) Tells curl to use the specified client certificate file when getting a | (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 | 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 | 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 | is the private key and the private certificate concatenated! See \fI--cert\fP | ||||||
| and \fI--key\fP to specify them independently. | 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. | 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 | (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 | certificate string can either be the name of a certificate/private key in the | ||||||
| user keychain. The private key corresponding to the certificate, and | system or user keychain, or the path to a PKCS#12-encoded certificate and | ||||||
| certificate chain (if any),  must also be present in the keychain. | 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. | If this option is used several times, the last one will be used. | ||||||
| .IP "--engine <name>" | .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! | 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. | 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" | .IP "-p, --proxytunnel" | ||||||
| When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP | 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 | 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" | .IP "--trace-time" | ||||||
| Prepends a time stamp to each trace or verbose line that curl displays. | Prepends a time stamp to each trace or verbose line that curl displays. | ||||||
| (Added in 7.14.0) | (Added in 7.14.0) | ||||||
| .IP "-u, --user <user:password>" | .IP "-u, --user <user:password;options>" | ||||||
| Specify the user name and password to use for server authentication. Overrides | Specify the user name, password and optional login options to use for server | ||||||
| \fI-n, --netrc\fP and \fI--netrc-optional\fP. | 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 | If you simply specify the user name, with or without the login options, curl | ||||||
| a password. | will prompt for a password. | ||||||
|  |  | ||||||
| If you use an SSPI-enabled curl binary and do NTLM authentication, you can | If you use an SSPI-enabled curl binary and perform NTLM authentication, you | ||||||
| force curl to pick up the user name and password from your environment by | can force curl to select the user name and password from your environment by | ||||||
| simply specifying a single colon with this option: "-u :". | 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. | If this option is used several times, the last one will be used. | ||||||
| .IP "-U, --proxy-user <user:password>" | .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. | If this option is used several times, the last one will be used. | ||||||
| .IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>" | .IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>" | ||||||
| Use the specified HTTP proxy. If the port number is not specified, it is | Use the specified proxy. | ||||||
| assumed at port 1080. |  | ||||||
|  | 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 | 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 | 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 + | variables, including the protocol prefix (http://) and the embedded user + | ||||||
| password. | 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. | If this option is used several times, the last one will be used. | ||||||
| .IP "-X, --request <command>" | .IP "-X, --request <command>" | ||||||
| (HTTP) Specifies a custom request method to use when communicating with the | (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  \ |   persistant post-callback postit2 sepheaders simple simplepost simplessl  \ | ||||||
|   sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \ |   sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \ | ||||||
|   smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \ |   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 | # These examples require external dependencies that may not be commonly | ||||||
| # available on POSIX systems, so don't bother attempting to compile them here. | # 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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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. |      * bytes big and contains the remote file. | ||||||
|      * |      * | ||||||
|      * Do something nice with it! |      * 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); |     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 | data at all, and that data will then be delivered again to the callback when | ||||||
| the writing is later unpaused. | the writing is later unpaused. | ||||||
|  |  | ||||||
| NOTE: while it may feel tempting, take care and notice that you cannot call | While it may feel tempting, take care and notice that you cannot call this | ||||||
| this function from another thread. | 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 | When this function is called to unpause reading, the chance is high that you | ||||||
| will get your write callback called before this function returns. | 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 | 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 | 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, | 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 | SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only | ||||||
| only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on | passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1 | ||||||
| success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2 | (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2 | ||||||
| (CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is | (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 | free to work around the problem if possible. The latter can sometimes be done | ||||||
| by instead reading from the input or similar. | 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 | For more information about the individual components of a LDAP URL please | ||||||
| see RFC4516. | 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 | .B NOTES | ||||||
|  |  | ||||||
| Starting with version 7.20.0, the fragment part of the URI will not be sent as | 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, | 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 | as libcurl can determine the feature itself when the server supports the | ||||||
| SASL-IR CAPABILITY. | 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 | .SH HTTP OPTIONS | ||||||
| .IP CURLOPT_AUTOREFERER | .IP CURLOPT_AUTOREFERER | ||||||
| Pass a parameter set to 1 to enable this. When enabled, libcurl will | 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. | Default timeout is 0 (zero) which means it never times out. | ||||||
| .IP CURLOPT_TIMEOUT_MS | .IP CURLOPT_TIMEOUT_MS | ||||||
| Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If | An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds | ||||||
| libcurl is built to use the standard system name resolver, that portion | instead. If libcurl is built to use the standard system name resolver, that | ||||||
| of the transfer will still use full-second resolution for timeouts with | portion of the transfer will still use full-second resolution for timeouts | ||||||
| a minimum timeout allowed of one second. | 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) | (Added in 7.16.2) | ||||||
| .IP CURLOPT_LOW_SPEED_LIMIT | .IP CURLOPT_LOW_SPEED_LIMIT | ||||||
| Pass a long as parameter. It contains the transfer speed in bytes per second | 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. | supports this operation. The c-ares backend is the only such one. | ||||||
|  |  | ||||||
| (Added in 7.24.0) | (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 | .IP CURLOPT_ACCEPTTIMEOUT_MS | ||||||
| Pass a long telling libcurl the maximum number of milliseconds to wait for a | 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 | 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 | .SH SSL and SECURITY OPTIONS | ||||||
| .IP CURLOPT_SSLCERT | .IP CURLOPT_SSLCERT | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | 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 | the file name of your certificate. The default format is "P12" on Secure | ||||||
| changed with \fICURLOPT_SSLCERTTYPE\fP. | 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 | With NSS or Secure Transport, this can also be the nickname of the certificate | ||||||
| authenticate with. If you want to use a file from the current directory, please | you wish to authenticate with as it is named in the security database. If you | ||||||
| precede it with "./" prefix, in order to avoid confusion with a nickname. | 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) |  | ||||||
| .IP CURLOPT_SSLCERTTYPE | .IP CURLOPT_SSLCERTTYPE | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | 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 | the format of your certificate. Supported formats are "PEM" and "DER", except | ||||||
| in 7.9.3) | 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 | .IP CURLOPT_SSLKEY | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | 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 | 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 | (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 | 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 | .IP CURLOPT_SSLKEYTYPE | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | 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". | 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 | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * 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)" | .IP "CURLM_UNKNOWN_OPTION (6)" | ||||||
| curl_multi_setopt() with unsupported option | curl_multi_setopt() with unsupported option | ||||||
| (Added in 7.15.4) | (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" | .SH "CURLSHcode" | ||||||
| The "share" interface will return a CURLSHcode to indicate when an error has | The "share" interface will return a CURLSHcode to indicate when an error has | ||||||
| occurred.  Also consider \fIcurl_share_strerror(3)\fP. | 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 | .\" * This software is licensed as described in the file COPYING, which | ||||||
| .\" * you should have received as part of this distribution. The terms | .\" * 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. | for details. | ||||||
|  |  | ||||||
| To transfer files, you always set up an "easy handle" using | 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 | \fIcurl_easy_init(3)\fP for a single specific transfer (in either | ||||||
| the option of using the "easy" interface, or the "multi" interface. | 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 | 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 | \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 | 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 | 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 | 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 | 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 | 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. | several transfers, if the conditions are right. | ||||||
|  |  | ||||||
| libcurl will \fBalways\fP attempt to use persistent connections. Whenever you | 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 | use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl | ||||||
| attempt to use an existing connection to do the transfer, and if none exists | will attempt to use an existing connection to do the transfer, and if none | ||||||
| it'll open a new one that will be subject for re-use on a possible following | exists it'll open a new one that will be subject for re-use on a possible | ||||||
| call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP. | 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 | 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 | do as many of your file transfers as possible using the same handle. | ||||||
| you call \fIcurl_easy_cleanup(3)\fP, all the possibly open connections held by |  | ||||||
| libcurl will be closed and forgotten. |  | ||||||
|  |  | ||||||
| Note that the options set with \fIcurl_easy_setopt(3)\fP will be used on | If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all | ||||||
| every repeated \fIcurl_easy_perform(3)\fP call. | 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" | .SH "GLOBAL CONSTANTS" | ||||||
| There are a variety of constants that libcurl uses, mainly through its | There are a variety of constants that libcurl uses, mainly through its | ||||||
| internal use of other libraries, which are too complicated for the | 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_LIBRARY_NOT_FOUND         7.1           7.17.0 | ||||||
| CURLE_LOGIN_DENIED              7.13.1 | CURLE_LOGIN_DENIED              7.13.1 | ||||||
| CURLE_MALFORMAT_USER            7.1           7.17.0 | CURLE_MALFORMAT_USER            7.1           7.17.0 | ||||||
| CURLE_NO_CONNECTION_AVAILABLE   7.30.0 |  | ||||||
| CURLE_NOT_BUILT_IN              7.21.5 | CURLE_NOT_BUILT_IN              7.21.5 | ||||||
|  | CURLE_NO_CONNECTION_AVAILABLE   7.30.0 | ||||||
| CURLE_OK                        7.1 | CURLE_OK                        7.1 | ||||||
| CURLE_OPERATION_TIMEDOUT        7.10.2 | CURLE_OPERATION_TIMEDOUT        7.10.2 | ||||||
| CURLE_OPERATION_TIMEOUTED       7.1           7.17.0 | CURLE_OPERATION_TIMEOUTED       7.1           7.17.0 | ||||||
| @@ -270,10 +270,10 @@ CURLKHTYPE_RSA1                 7.19.6 | |||||||
| CURLKHTYPE_UNKNOWN              7.19.6 | CURLKHTYPE_UNKNOWN              7.19.6 | ||||||
| CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 | CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 | ||||||
| CURLMOPT_CONTENT_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_HOST_CONNECTIONS   7.30.0 | ||||||
| CURLMOPT_MAX_PIPELINE_LENGTH    7.30.0 | CURLMOPT_MAX_PIPELINE_LENGTH    7.30.0 | ||||||
| CURLMOPT_MAX_TOTAL_CONNECTIONS  7.30.0 | CURLMOPT_MAX_TOTAL_CONNECTIONS  7.30.0 | ||||||
| CURLMOPT_MAXCONNECTS            7.16.3 |  | ||||||
| CURLMOPT_PIPELINING             7.16.0 | CURLMOPT_PIPELINING             7.16.0 | ||||||
| CURLMOPT_PIPELINING_SERVER_BL   7.30.0 | CURLMOPT_PIPELINING_SERVER_BL   7.30.0 | ||||||
| CURLMOPT_PIPELINING_SITE_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 | CURLMOPT_TIMERFUNCTION          7.16.0 | ||||||
| CURLMSG_DONE                    7.9.6 | CURLMSG_DONE                    7.9.6 | ||||||
| CURLMSG_NONE                    7.9.6 | CURLMSG_NONE                    7.9.6 | ||||||
|  | CURLM_ADDED_ALREADY             7.32.1 | ||||||
| CURLM_BAD_EASY_HANDLE           7.9.6 | CURLM_BAD_EASY_HANDLE           7.9.6 | ||||||
| CURLM_BAD_HANDLE                7.9.6 | CURLM_BAD_HANDLE                7.9.6 | ||||||
| CURLM_BAD_SOCKET                7.15.4 | CURLM_BAD_SOCKET                7.15.4 | ||||||
| @@ -331,6 +332,9 @@ CURLOPT_DEBUGDATA               7.9.6 | |||||||
| CURLOPT_DEBUGFUNCTION           7.9.6 | CURLOPT_DEBUGFUNCTION           7.9.6 | ||||||
| CURLOPT_DIRLISTONLY             7.17.0 | CURLOPT_DIRLISTONLY             7.17.0 | ||||||
| CURLOPT_DNS_CACHE_TIMEOUT       7.9.3 | 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_SERVERS             7.24.0 | ||||||
| CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1 | CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1 | ||||||
| CURLOPT_EGDSOCKET               7.7 | CURLOPT_EGDSOCKET               7.7 | ||||||
| @@ -527,6 +531,7 @@ CURLOPT_WRITEHEADER             7.1 | |||||||
| CURLOPT_WRITEINFO               7.1 | CURLOPT_WRITEINFO               7.1 | ||||||
| CURLOPT_XFERINFODATA            7.32.0 | CURLOPT_XFERINFODATA            7.32.0 | ||||||
| CURLOPT_XFERINFOFUNCTION        7.32.0 | CURLOPT_XFERINFOFUNCTION        7.32.0 | ||||||
|  | CURLOPT_XOAUTH2_BEARER          7.33.0 | ||||||
| CURLPAUSE_ALL                   7.18.0 | CURLPAUSE_ALL                   7.18.0 | ||||||
| CURLPAUSE_CONT                  7.18.0 | CURLPAUSE_CONT                  7.18.0 | ||||||
| CURLPAUSE_RECV                  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_OK                 7.9.8 | ||||||
| CURL_FORMADD_OPTION_TWICE       7.9.8 | CURL_FORMADD_OPTION_TWICE       7.9.8 | ||||||
| CURL_FORMADD_UNKNOWN_OPTION     7.9.8 | CURL_FORMADD_UNKNOWN_OPTION     7.9.8 | ||||||
|  | CURL_GLOBAL_ACK_EINTR           7.30.0 | ||||||
| CURL_GLOBAL_ALL                 7.8 | CURL_GLOBAL_ALL                 7.8 | ||||||
| CURL_GLOBAL_DEFAULT             7.8 | CURL_GLOBAL_DEFAULT             7.8 | ||||||
| CURL_GLOBAL_NOTHING             7.8 | CURL_GLOBAL_NOTHING             7.8 | ||||||
| CURL_GLOBAL_SSL                 7.8 | CURL_GLOBAL_SSL                 7.8 | ||||||
| CURL_GLOBAL_WIN32               7.8.1 | 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_0           7.9.1 | ||||||
| CURL_HTTP_VERSION_1_1           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_HTTP_VERSION_NONE          7.9.1 | ||||||
| CURL_IPRESOLVE_V4               7.10.8 | CURL_IPRESOLVE_V4               7.10.8 | ||||||
| CURL_IPRESOLVE_V6               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_CURLDEBUG          7.19.6 | ||||||
| CURL_VERSION_DEBUG              7.10.6 | CURL_VERSION_DEBUG              7.10.6 | ||||||
| CURL_VERSION_GSSNEGOTIATE       7.10.6 | CURL_VERSION_GSSNEGOTIATE       7.10.6 | ||||||
|  | CURL_VERSION_HTTP2              7.33.0 | ||||||
| CURL_VERSION_IDN                7.12.0 | CURL_VERSION_IDN                7.12.0 | ||||||
| CURL_VERSION_IPV6               7.10 | CURL_VERSION_IPV6               7.10 | ||||||
| CURL_VERSION_KERBEROS4          7.10 | CURL_VERSION_KERBEROS4          7.10 | ||||||
|   | |||||||
| @@ -645,16 +645,18 @@ typedef enum { | |||||||
|  |  | ||||||
| #define CURL_ERROR_SIZE 256 | #define CURL_ERROR_SIZE 256 | ||||||
|  |  | ||||||
| struct curl_khkey { | enum curl_khtype { | ||||||
|   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 { |  | ||||||
|   CURLKHTYPE_UNKNOWN, |   CURLKHTYPE_UNKNOWN, | ||||||
|   CURLKHTYPE_RSA1, |   CURLKHTYPE_RSA1, | ||||||
|   CURLKHTYPE_RSA, |   CURLKHTYPE_RSA, | ||||||
|   CURLKHTYPE_DSS |   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 | /* this is the set of return values expected from the curl_sshkeycallback | ||||||
| @@ -1551,6 +1553,22 @@ typedef enum { | |||||||
|    * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ |    * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ | ||||||
|   CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), |   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 */ |   CURLOPT_LASTENTRY /* the last unused */ | ||||||
| } CURLoption; | } CURLoption; | ||||||
|  |  | ||||||
| @@ -1603,6 +1621,7 @@ enum { | |||||||
|                              for us! */ |                              for us! */ | ||||||
|   CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */ |   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_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 */ |   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_CURLDEBUG (1<<13) /* debug memory tracking supported */ | ||||||
| #define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is 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_NTLM_WB   (1<<15) /* NTLM delegating to winbind helper */ | ||||||
|  | #define CURL_VERSION_HTTP2     (1<<16) /* HTTP2 support built-in */ | ||||||
|  |  | ||||||
|  /* |  /* | ||||||
|  * NAME curl_version_info() |  * NAME curl_version_info() | ||||||
|   | |||||||
| @@ -30,12 +30,12 @@ | |||||||
|  |  | ||||||
| /* This is the version number of the libcurl package from which this header | /* This is the version number of the libcurl package from which this header | ||||||
|    file origins: */ |    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 | /* The numeric version number is also available "in parts" by using these | ||||||
|    defines: */ |    defines: */ | ||||||
| #define LIBCURL_VERSION_MAJOR 7 | #define LIBCURL_VERSION_MAJOR 7 | ||||||
| #define LIBCURL_VERSION_MINOR 32 | #define LIBCURL_VERSION_MINOR 33 | ||||||
| #define LIBCURL_VERSION_PATCH 0 | #define LIBCURL_VERSION_PATCH 0 | ||||||
|  |  | ||||||
| /* This is the numeric version of the libcurl version number, meant for easier | /* 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 |    and it is always a greater number in a more recent release. It makes | ||||||
|    comparisons with greater than and less than work. |    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 |  * 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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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_INTERNAL_ERROR,  /* this is a libcurl bug */ | ||||||
|   CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */ |   CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */ | ||||||
|   CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */ |   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 |   CURLM_LAST | ||||||
| } CURLMcode; | } CURLMcode; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -264,6 +264,11 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, | |||||||
|    (option) == CURLOPT_RTSP_SESSION_ID ||                                     \ |    (option) == CURLOPT_RTSP_SESSION_ID ||                                     \ | ||||||
|    (option) == CURLOPT_RTSP_STREAM_URI ||                                     \ |    (option) == CURLOPT_RTSP_STREAM_URI ||                                     \ | ||||||
|    (option) == CURLOPT_RTSP_TRANSPORT ||                                      \ |    (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) |    0) | ||||||
|  |  | ||||||
| /* evaluates to true if option takes a curl_write_callback argument */ | /* 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	\ | 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	\ |   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	\ |   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		\ |   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	\ |   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	\ |   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_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		\ |   curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c		\ | ||||||
|   hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.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	\ | 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	\ |   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	\ |   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		\ |   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	\ |   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	\ |   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	\ |   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_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	\ |   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)\imap.obj \ | ||||||
| 	$(DIROBJ)\inet_ntop.obj \ | 	$(DIROBJ)\inet_ntop.obj \ | ||||||
| 	$(DIROBJ)\inet_pton.obj \ | 	$(DIROBJ)\inet_pton.obj \ | ||||||
| 	$(DIROBJ)\krb4.obj \ |  | ||||||
| 	$(DIROBJ)\krb5.obj \ | 	$(DIROBJ)\krb5.obj \ | ||||||
| 	$(DIROBJ)\ldap.obj \ | 	$(DIROBJ)\ldap.obj \ | ||||||
| 	$(DIROBJ)\llist.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 | #endif | ||||||
|   return result; |   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 */ | #endif /* CURLRES_ARES */ | ||||||
|   | |||||||
| @@ -265,7 +265,7 @@ static int getaddrinfo_complete(struct connectdata *conn) | |||||||
| static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) | static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) | ||||||
| { | { | ||||||
|   struct thread_sync_data *tsd = (struct thread_sync_data*)arg; |   struct thread_sync_data *tsd = (struct thread_sync_data*)arg; | ||||||
|   char   service [NI_MAXSERV]; |   char service[12]; | ||||||
|   int rc; |   int rc; | ||||||
|  |  | ||||||
|   snprintf(service, sizeof(service), "%d", tsd->port); |   snprintf(service, sizeof(service), "%d", tsd->port); | ||||||
| @@ -559,7 +559,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, | |||||||
|   struct in_addr in; |   struct in_addr in; | ||||||
|   Curl_addrinfo *res; |   Curl_addrinfo *res; | ||||||
|   int error; |   int error; | ||||||
|   char sbuf[NI_MAXSERV]; |   char sbuf[12]; | ||||||
|   int pf = PF_INET; |   int pf = PF_INET; | ||||||
| #ifdef CURLRES_IPV6 | #ifdef CURLRES_IPV6 | ||||||
|   struct in6_addr in6; |   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 */ | #endif /* CURLRES_THREADED */ | ||||||
|   | |||||||
| @@ -390,21 +390,6 @@ | |||||||
| #  define SIZEOF_SIZE_T 4 | #  define SIZEOF_SIZE_T 4 | ||||||
| #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 |  | ||||||
|  |  | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| /*               BSD-style lwIP TCP/IP stack SPECIFIC               */ | /*               BSD-style lwIP TCP/IP stack SPECIFIC               */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| @@ -572,6 +557,25 @@ | |||||||
| #  endif | #  endif | ||||||
| #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                        */ | /*                        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); |   *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 |      superceeds an already existing cookie, which it may if the previous have | ||||||
|      the same domain and path as this */ |      the same domain and path as this */ | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   clist = c->cookies; |   clist = c->cookies; | ||||||
|   replace_old = FALSE; |   replace_old = FALSE; | ||||||
|   while(clist) { |   while(clist) { | ||||||
| @@ -931,6 +962,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, | |||||||
|   if(!c || !c->cookies) |   if(!c || !c->cookies) | ||||||
|     return NULL; /* no cookie struct or no cookies in the struct */ |     return NULL; /* no cookie struct or no cookies in the struct */ | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   co = c->cookies; |   co = c->cookies; | ||||||
|  |  | ||||||
|   while(co) { |   while(co) { | ||||||
| @@ -1173,6 +1207,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) | |||||||
|        destination file */ |        destination file */ | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  |   /* at first, remove expired cookies */ | ||||||
|  |   remove_expired(c); | ||||||
|  |  | ||||||
|   if(strequal("-", dumphere)) { |   if(strequal("-", dumphere)) { | ||||||
|     /* use stdout */ |     /* use stdout */ | ||||||
|     out = stdout; |     out = stdout; | ||||||
|   | |||||||
| @@ -52,12 +52,14 @@ | |||||||
| #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ | #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ | ||||||
|  |  | ||||||
| #define CURL_BUILD_IOS 0 | #define CURL_BUILD_IOS 0 | ||||||
|  | #define CURL_BUILD_IOS_7 0 | ||||||
| #define CURL_BUILD_MAC 1 | #define CURL_BUILD_MAC 1 | ||||||
| /* This is the maximum API level we are allowed to use when building: */ | /* 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_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_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_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_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 | /* These macros mean "the following code is present to allow runtime backward | ||||||
|    compatibility with at least this cat or earlier": |    compatibility with at least this cat or earlier": | ||||||
|    (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET |    (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_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_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_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 | #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE | ||||||
| #define CURL_BUILD_IOS 1 | #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 0 | ||||||
| #define CURL_BUILD_MAC_10_5 0 | #define CURL_BUILD_MAC_10_5 0 | ||||||
| #define CURL_BUILD_MAC_10_6 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"; |       return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; | ||||||
|       break; |       break; | ||||||
| #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ | #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"; |   return "TLS_NULL_WITH_NULL_NULL"; | ||||||
| } | } | ||||||
| @@ -819,6 +927,68 @@ static OSStatus CopyIdentityWithLabel(char *label, | |||||||
|   return status; |   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, | static CURLcode darwinssl_connect_step1(struct connectdata *conn, | ||||||
|                                         int sockindex) |                                         int sockindex) | ||||||
| { | { | ||||||
| @@ -988,9 +1158,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|  |  | ||||||
|   if(data->set.str[STRING_CERT]) { |   if(data->set.str[STRING_CERT]) { | ||||||
|     SecIdentityRef cert_and_key = NULL; |     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); |       err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key); | ||||||
|  |  | ||||||
|     if(err == noErr) { |     if(err == noErr) { | ||||||
|       SecCertificateRef cert = NULL; |       SecCertificateRef cert = NULL; | ||||||
|       CFTypeRef certs_c[1]; |       CFTypeRef certs_c[1]; | ||||||
| @@ -1027,8 +1215,29 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|       CFRelease(cert_and_key); |       CFRelease(cert_and_key); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       failf(data, "SSL: Can't find the certificate \"%s\" and its private key " |       switch(err) { | ||||||
|                   "in the Keychain.", data->set.str[STRING_CERT]); |         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; |       return CURLE_SSL_CERTPROBLEM; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -1121,11 +1330,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, | |||||||
|         case SSL_NULL_WITH_NULL_NULL: |         case SSL_NULL_WITH_NULL_NULL: | ||||||
|         case SSL_RSA_WITH_NULL_MD5: |         case SSL_RSA_WITH_NULL_MD5: | ||||||
|         case SSL_RSA_WITH_NULL_SHA: |         case SSL_RSA_WITH_NULL_SHA: | ||||||
|  |         case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ | ||||||
|         case SSL_FORTEZZA_DMS_WITH_NULL_SHA: |         case SSL_FORTEZZA_DMS_WITH_NULL_SHA: | ||||||
|         case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ |         case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ | ||||||
|         case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ |         case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ | ||||||
|         case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ |         case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ | ||||||
|         case 0xC010: /* TLS_ECDHE_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: */ |         /* Disable anonymous ciphersuites: */ | ||||||
|         case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: |         case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: | ||||||
|         case SSL_DH_anon_WITH_RC4_128_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(all_ciphers); | ||||||
|   Curl_safefree(allowed_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! */ |   /* Check if there's a cached ID we can/should use here! */ | ||||||
|   if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, |   if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, | ||||||
|     &ssl_sessionid_len)) { |     &ssl_sessionid_len)) { | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ | |||||||
|  * RFC2831 DIGEST-MD5 authentication |  * RFC2831 DIGEST-MD5 authentication | ||||||
|  * RFC4422 Simple Authentication and Security Layer (SASL) |  * RFC4422 Simple Authentication and Security Layer (SASL) | ||||||
|  * RFC4616 PLAIN authentication |  * 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, |                                         const char *passwdp, | ||||||
|                                         char **outptr, size_t *outlen) |                                         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 ulen; | ||||||
|   size_t plen; |   size_t plen; | ||||||
|  |  | ||||||
|   ulen = strlen(userp); |   ulen = strlen(userp); | ||||||
|   plen = strlen(passwdp); |   plen = strlen(passwdp); | ||||||
|  |  | ||||||
|   if(2 * ulen + plen + 2 > sizeof(plainauth)) { |   plainauth = malloc(2 * ulen + plen + 2); | ||||||
|  |   if(!plainauth) { | ||||||
|     *outlen = 0; |     *outlen = 0; | ||||||
|     *outptr = NULL; |     *outptr = NULL; | ||||||
|  |  | ||||||
|     /* Plainauth too small */ |  | ||||||
|     return CURLE_OUT_OF_MEMORY; |     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); |   memcpy(plainauth + 2 * ulen + 2, passwdp, plen); | ||||||
|  |  | ||||||
|   /* Base64 encode the reply */ |   /* 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); |                               outlen); | ||||||
|  |   Curl_safefree(plainauth); | ||||||
|  |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -190,7 +193,7 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | |||||||
|   size_t chlglen = 0; |   size_t chlglen = 0; | ||||||
|   HMAC_context *ctxt; |   HMAC_context *ctxt; | ||||||
|   unsigned char digest[MD5_DIGEST_LEN]; |   unsigned char digest[MD5_DIGEST_LEN]; | ||||||
|   char response[MAX_CURL_USER_LENGTH + 2 * MD5_DIGEST_LEN + 1]; |   char *response; | ||||||
|  |  | ||||||
|   /* Decode the challenge if necessary */ |   /* Decode the challenge if necessary */ | ||||||
|   if(chlg64len && *chlg64 != '=') { |   if(chlg64len && *chlg64 != '=') { | ||||||
| @@ -220,14 +223,19 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, | |||||||
|   Curl_HMAC_final(ctxt, digest); |   Curl_HMAC_final(ctxt, digest); | ||||||
|  |  | ||||||
|   /* Prepare the response */ |   /* 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", |       "%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], |            userp, digest[0], digest[1], digest[2], digest[3], digest[4], | ||||||
|            digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], |            digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], | ||||||
|            digest[11], digest[12], digest[13], digest[14], digest[15]); |            digest[11], digest[12], digest[13], digest[14], digest[15]); | ||||||
|  |   if(!response) | ||||||
|  |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   /* Base64 encode the reply */ |   /* 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 */ | #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() |  * Curl_sasl_cleanup() | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -24,6 +24,10 @@ | |||||||
|  |  | ||||||
| #include "pingpong.h" | #include "pingpong.h" | ||||||
|  |  | ||||||
|  | /* Authentication mechanism values */ | ||||||
|  | #define SASL_AUTH_NONE          0 | ||||||
|  | #define SASL_AUTH_ANY           ~0U | ||||||
|  |  | ||||||
| /* Authentication mechanism flags */ | /* Authentication mechanism flags */ | ||||||
| #define SASL_MECH_LOGIN             (1 << 0) | #define SASL_MECH_LOGIN             (1 << 0) | ||||||
| #define SASL_MECH_PLAIN             (1 << 1) | #define SASL_MECH_PLAIN             (1 << 1) | ||||||
| @@ -32,10 +36,22 @@ | |||||||
| #define SASL_MECH_GSSAPI            (1 << 4) | #define SASL_MECH_GSSAPI            (1 << 4) | ||||||
| #define SASL_MECH_EXTERNAL          (1 << 5) | #define SASL_MECH_EXTERNAL          (1 << 5) | ||||||
| #define SASL_MECH_NTLM              (1 << 6) | #define SASL_MECH_NTLM              (1 << 6) | ||||||
|  | #define SASL_MECH_XOAUTH2           (1 << 7) | ||||||
|  |  | ||||||
| /* Authentication mechanism values */ | /* Authentication mechanism strings */ | ||||||
| #define SASL_AUTH_NONE          0 | #define SASL_MECH_STRING_LOGIN      "LOGIN" | ||||||
| #define SASL_AUTH_ANY           ~0 | #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 */ | /* This is used to generate a base64 encoded PLAIN authentication message */ | ||||||
| CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, | 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 */ | #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 | /* This is used to cleanup any libraries or curl modules used by the sasl | ||||||
|    functions */ |    functions */ | ||||||
| void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); | void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| #ifndef HEADER_CURL_KRB4_H | #ifndef HEADER_CURL_SECURITY_H | ||||||
| #define HEADER_CURL_KRB4_H | #define HEADER_CURL_SECURITY_H | ||||||
| /***************************************************************************
 | /***************************************************************************
 | ||||||
|  *                                  _   _ ____  _ |  *                                  _   _ ____  _ | ||||||
|  *  Project                     ___| | | |  _ \| | |  *  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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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 *); |   int (*decode)(void *, void*, int, int, struct connectdata *); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #define AUTH_OK         0 | #define AUTH_OK         0 | ||||||
| #define AUTH_CONTINUE   1 | #define AUTH_CONTINUE   1 | ||||||
| #define AUTH_ERROR      2 | #define AUTH_ERROR      2 | ||||||
| 
 | 
 | ||||||
| #ifdef HAVE_KRB4 |  | ||||||
| extern struct Curl_sec_client_mech Curl_krb4_client_mech; |  | ||||||
| #endif |  | ||||||
| #ifdef HAVE_GSSAPI | #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 *, | int Curl_sec_read_msg (struct connectdata *conn, char *, | ||||||
|                        enum protection_level); |                        enum protection_level); | ||||||
| void Curl_sec_end (struct connectdata *); | void Curl_sec_end (struct connectdata *); | ||||||
| CURLcode Curl_sec_login (struct connectdata *); | CURLcode Curl_sec_login (struct connectdata *); | ||||||
| int Curl_sec_request_prot (struct connectdata *conn, const char *level); | 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. |  * (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 ERRNO         ((int)GetLastError()) | ||||||
| #define SET_ERRNO(x)  (SetLastError((DWORD)(x))) | #define SET_ERRNO(x)  (SetLastError((DWORD)(x))) | ||||||
| #else | #else | ||||||
|   | |||||||
							
								
								
									
										438
									
								
								lib/easy.c
									
									
									
									
									
								
							
							
						
						
									
										438
									
								
								lib/easy.c
									
									
									
									
									
								
							| @@ -453,70 +453,275 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...) | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | #ifdef CURLDEBUG | ||||||
|  * curl_easy_perform() is the external interface that performs a blocking |  | ||||||
|  * transfer as previously setup. | 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, |  * Callback that gets called with a new value when the timeout should be | ||||||
|  * runs curl_multi_perform() until the transfer is done, then detaches the |  * updated. | ||||||
|  * 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. |  | ||||||
|  */ |  */ | ||||||
| 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; |   bool done = FALSE; | ||||||
|   int rc; |   CURLMcode mcode; | ||||||
|   struct SessionHandle *data = easy; |   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 |   int without_fds = 0;  /* count number of consecutive returns from | ||||||
|                            curl_multi_wait() without any filedescriptors */ |                            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) { |   while(!done && !mcode) { | ||||||
|     int still_running; |     int still_running; | ||||||
| @@ -556,17 +761,85 @@ CURLcode curl_easy_perform(CURL *easy) | |||||||
|  |  | ||||||
|     /* only read 'still_running' if curl_multi_perform() return OK */ |     /* only read 'still_running' if curl_multi_perform() return OK */ | ||||||
|     if((mcode == CURLM_OK) && !still_running) { |     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) { |       if(msg) { | ||||||
|         code = msg->data.result; |         code = msg->data.result; | ||||||
|         done = TRUE; |         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 |   /* ignoring the return code isn't nice, but atm we can't really handle | ||||||
|      a failure here, room for future improvement! */ |      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); |   sigpipe_restore(&pipe_st); | ||||||
|  |  | ||||||
| @@ -574,6 +847,28 @@ CURLcode curl_easy_perform(CURL *easy) | |||||||
|   return code; |   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 |  * curl_easy_cleanup() is the external interface to cleaning/freeing the given | ||||||
|  * easy handle. |  * easy handle. | ||||||
| @@ -591,22 +886,6 @@ void curl_easy_cleanup(CURL *curl) | |||||||
|   sigpipe_restore(&pipe_st); |   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 |  * curl_easy_getinfo() is an external interface that allows an app to retrieve | ||||||
|  * information from a performed transfer and similar. |  * information from a performed transfer and similar. | ||||||
| @@ -703,8 +982,6 @@ CURL *curl_easy_duphandle(CURL *incurl) | |||||||
|  |  | ||||||
|   Curl_convert_setup(outcurl); |   Curl_convert_setup(outcurl); | ||||||
|  |  | ||||||
|   Curl_easy_initHandleData(outcurl); |  | ||||||
|  |  | ||||||
|   outcurl->magic = CURLEASY_MAGIC_NUMBER; |   outcurl->magic = CURLEASY_MAGIC_NUMBER; | ||||||
|  |  | ||||||
|   /* we reach this point and thus we are OK */ |   /* we reach this point and thus we are OK */ | ||||||
| @@ -738,7 +1015,7 @@ void curl_easy_reset(CURL *curl) | |||||||
|  |  | ||||||
|   data->state.path = NULL; |   data->state.path = NULL; | ||||||
|  |  | ||||||
|   Curl_safefree(data->state.proto.generic); |   Curl_free_request_state(data); | ||||||
|  |  | ||||||
|   /* zero out UserDefined data: */ |   /* zero out UserDefined data: */ | ||||||
|   Curl_freeset(data); |   Curl_freeset(data); | ||||||
| @@ -748,9 +1025,6 @@ void curl_easy_reset(CURL *curl) | |||||||
|   /* zero out Progress data: */ |   /* zero out Progress data: */ | ||||||
|   memset(&data->progress, 0, sizeof(struct Progress)); |   memset(&data->progress, 0, sizeof(struct Progress)); | ||||||
|  |  | ||||||
|   /* init Handle data */ |  | ||||||
|   Curl_easy_initHandleData(data); |  | ||||||
|  |  | ||||||
|   data->progress.flags |= PGRS_HIDE; |   data->progress.flags |= PGRS_HIDE; | ||||||
|   data->state.current_speed = -1; /* init to negative == impossible */ |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -25,9 +25,9 @@ | |||||||
| /* | /* | ||||||
|  * Prototypes for library-wide functions provided by easy.c |  * Prototypes for library-wide functions provided by easy.c | ||||||
|  */ |  */ | ||||||
| void Curl_easy_addmulti(struct SessionHandle *data, void *multi); | #ifdef CURLDEBUG | ||||||
|  | CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy); | ||||||
| void Curl_easy_initHandleData(struct SessionHandle *data); | #endif | ||||||
|  |  | ||||||
| #endif /* HEADER_CURL_EASYIF_H */ | #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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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_connect(struct connectdata *conn, bool *done); | ||||||
| static CURLcode file_disconnect(struct connectdata *conn, | static CURLcode file_disconnect(struct connectdata *conn, | ||||||
|                                 bool dead_connection); |                                 bool dead_connection); | ||||||
|  | static CURLcode file_setup_connection(struct connectdata *conn); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * FILE scheme handler. |  * FILE scheme handler. | ||||||
| @@ -98,7 +98,7 @@ static CURLcode file_disconnect(struct connectdata *conn, | |||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_file = { | const struct Curl_handler Curl_handler_file = { | ||||||
|   "FILE",                               /* scheme */ |   "FILE",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   file_setup_connection,                /* setup_connection */ | ||||||
|   file_do,                              /* do_it */ |   file_do,                              /* do_it */ | ||||||
|   file_done,                            /* done */ |   file_done,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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 |   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 |   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; |   struct SessionHandle *data = conn->data; | ||||||
|   char *real_path; |   char *real_path; | ||||||
|   struct FILEPROTO *file; |   struct FILEPROTO *file = data->req.protop; | ||||||
|   int fd; |   int fd; | ||||||
| #ifdef DOS_FILESYSTEM | #ifdef DOS_FILESYSTEM | ||||||
|   int i; |   int i; | ||||||
|   char *actual_path; |   char *actual_path; | ||||||
| #endif | #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); |   real_path = curl_easy_unescape(data, data->state.path, 0, NULL); | ||||||
|   if(!real_path) |   if(!real_path) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     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 | #ifdef DOS_FILESYSTEM | ||||||
|   /* If the first character is a slash, and there's |   /* If the first character is a slash, and there's | ||||||
|      something that looks like a drive at the beginning of |      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, | static CURLcode file_done(struct connectdata *conn, | ||||||
|                                CURLcode status, bool premature) |                                CURLcode status, bool premature) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->state.proto.file; |   struct FILEPROTO *file = conn->data->req.protop; | ||||||
|   (void)status; /* not used */ |   (void)status; /* not used */ | ||||||
|   (void)premature; /* not used */ |   (void)premature; /* not used */ | ||||||
|  |  | ||||||
| @@ -280,7 +268,7 @@ static CURLcode file_done(struct connectdata *conn, | |||||||
| static CURLcode file_disconnect(struct connectdata *conn, | static CURLcode file_disconnect(struct connectdata *conn, | ||||||
|                                 bool dead_connection) |                                 bool dead_connection) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->state.proto.file; |   struct FILEPROTO *file = conn->data->req.protop; | ||||||
|   (void)dead_connection; /* not used */ |   (void)dead_connection; /* not used */ | ||||||
|  |  | ||||||
|   if(file) { |   if(file) { | ||||||
| @@ -302,7 +290,7 @@ static CURLcode file_disconnect(struct connectdata *conn, | |||||||
|  |  | ||||||
| static CURLcode file_upload(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); |   const char *dir = strchr(file->path, DIRSEP); | ||||||
|   int fd; |   int fd; | ||||||
|   int mode; |   int mode; | ||||||
| @@ -440,6 +428,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) | |||||||
|   curl_off_t bytecount = 0; |   curl_off_t bytecount = 0; | ||||||
|   int fd; |   int fd; | ||||||
|   struct timeval now = Curl_tvnow(); |   struct timeval now = Curl_tvnow(); | ||||||
|  |   struct FILEPROTO *file; | ||||||
|  |  | ||||||
|   *done = TRUE; /* unconditionally */ |   *done = TRUE; /* unconditionally */ | ||||||
|  |  | ||||||
| @@ -449,8 +438,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done) | |||||||
|   if(data->set.upload) |   if(data->set.upload) | ||||||
|     return file_upload(conn); |     return file_upload(conn); | ||||||
|  |  | ||||||
|  |   file = conn->data->req.protop; | ||||||
|  |  | ||||||
|   /* get the fd from the connection phase */ |   /* 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 */ |   /* VMS: This only works reliable for STREAMLF files */ | ||||||
|   if(-1 != fstat(fd, &statbuf)) { |   if(-1 != fstat(fd, &statbuf)) { | ||||||
|   | |||||||
							
								
								
									
										237
									
								
								lib/ftp.c
									
									
									
									
									
								
							
							
						
						
									
										237
									
								
								lib/ftp.c
									
									
									
									
									
								
							| @@ -59,11 +59,7 @@ | |||||||
| #include "ftp.h" | #include "ftp.h" | ||||||
| #include "fileinfo.h" | #include "fileinfo.h" | ||||||
| #include "ftplistparser.h" | #include "ftplistparser.h" | ||||||
|  | #include "curl_sec.h" | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) |  | ||||||
| #include "krb4.h" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include "strtoofft.h" | #include "strtoofft.h" | ||||||
| #include "strequal.h" | #include "strequal.h" | ||||||
| #include "sslgen.h" | #include "sslgen.h" | ||||||
| @@ -225,7 +221,7 @@ const struct Curl_handler Curl_handler_ftps = { | |||||||
|  |  | ||||||
| static const struct Curl_handler Curl_handler_ftp_proxy = { | static const struct Curl_handler Curl_handler_ftp_proxy = { | ||||||
|   "FTP",                                /* scheme */ |   "FTP",                                /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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 = { | static const struct Curl_handler Curl_handler_ftps_proxy = { | ||||||
|   "FTPS",                               /* scheme */ |   "FTPS",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -493,7 +489,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) | |||||||
| static CURLcode InitiateTransfer(struct connectdata *conn) | static CURLcode InitiateTransfer(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct FTP *ftp = data->state.proto.ftp; |   struct FTP *ftp = data->req.protop; | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|  |  | ||||||
|   if(conn->ssl[SECONDARYSOCKET].use) { |   if(conn->ssl[SECONDARYSOCKET].use) { | ||||||
| @@ -615,7 +611,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, | |||||||
| { | { | ||||||
|   struct connectdata *conn = pp->conn; |   struct connectdata *conn = pp->conn; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   char * const buf = data->state.buffer; |   char * const buf = data->state.buffer; | ||||||
| #endif | #endif | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
| @@ -623,7 +619,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, | |||||||
|  |  | ||||||
|   result = Curl_pp_readresp(sockfd, pp, &code, size); |   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 ***/ |   /* handle the security-oriented responses 6xx ***/ | ||||||
|   /* FIXME: some errorchecking perhaps... ***/ |   /* FIXME: some errorchecking perhaps... ***/ | ||||||
|   switch(code) { |   switch(code) { | ||||||
| @@ -775,17 +771,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ | |||||||
|   return result; |   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) | #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) | ||||||
|   /* for debug purposes */ |   /* for debug purposes */ | ||||||
|   static const char * const names[]={ | static const char * const ftp_state_names[]={ | ||||||
|   "STOP", |   "STOP", | ||||||
|   "WAIT220", |   "WAIT220", | ||||||
|   "AUTH", |   "AUTH", | ||||||
| @@ -823,11 +811,21 @@ static void _state(struct connectdata *conn, | |||||||
|   "QUIT" |   "QUIT" | ||||||
| }; | }; | ||||||
| #endif | #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; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
| #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) | #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) | ||||||
|   if(ftpc->state != newstate) |   if(ftpc->state != newstate) | ||||||
|     infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", |     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 | #endif | ||||||
|   ftpc->state = newstate; |   ftpc->state = newstate; | ||||||
| } | } | ||||||
| @@ -835,7 +833,7 @@ static void _state(struct connectdata *conn, | |||||||
| static CURLcode ftp_state_user(struct connectdata *conn) | static CURLcode ftp_state_user(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|   struct FTP *ftp = conn->data->state.proto.ftp; |   struct FTP *ftp = conn->data->req.protop; | ||||||
|   /* send USER */ |   /* send USER */ | ||||||
|   PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->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; |     return GETSOCK_BLANK; | ||||||
|  |  | ||||||
|   /* When in DO_MORE state, we could be either waiting for us to connect to a |   /* 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 |    * remote site, or we could wait for that site to connect to us. Or just | ||||||
|      handle ordinary commands. |    * 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. |  | ||||||
|  |  | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|   switch(ftpc->state) { |   if(FTP_STOP == ftpc->state) { | ||||||
|   case FTP_STOP: |     /* if stopped and still in this state, then we're also waiting for a | ||||||
|   case FTP_STOR: |        connect on the secondary connection */ | ||||||
|     break; |     socks[0] = conn->sock[FIRSTSOCKET]; | ||||||
|   default: |     socks[1] = conn->sock[SECONDARYSOCKET]; | ||||||
|  |  | ||||||
|  |     return GETSOCK_READSOCK(FIRSTSOCKET) | | ||||||
|  |       GETSOCK_WRITESOCK(SECONDARYSOCKET); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|     return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); |     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. | /* 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 |    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) | static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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 SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|   if(ftp->transfer != FTPTRANSFER_BODY) { |   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) | static CURLcode ftp_state_rest(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { |   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) | static CURLcode ftp_state_size(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { |   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) | static CURLcode ftp_state_type(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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 SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
| @@ -1614,7 +1602,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, | |||||||
|                                    bool sizechecked) |                                    bool sizechecked) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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 SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   int seekerr = CURL_SEEKFUNC_OK; |   int seekerr = CURL_SEEKFUNC_OK; | ||||||
| @@ -1712,7 +1700,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   bool quote=FALSE; |   bool quote=FALSE; | ||||||
|   struct curl_slist *item; |   struct curl_slist *item; | ||||||
| @@ -2058,13 +2046,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, | |||||||
|      * FTP pointer |      * FTP pointer | ||||||
|      */ |      */ | ||||||
|     struct HTTP http_proxy; |     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)); |     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); |     result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); | ||||||
|  |  | ||||||
|     data->state.proto.ftp = ftp_save; |     data->req.protop = ftp_save; | ||||||
|  |  | ||||||
|     if(result) |     if(result) | ||||||
|       return result; |       return result; | ||||||
| @@ -2124,7 +2112,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data=conn->data; |   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 ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   switch(ftpcode) { |   switch(ftpcode) { | ||||||
| @@ -2258,7 +2246,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data=conn->data; |   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 ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if(data->set.max_filesize && (filesize > data->set.max_filesize)) { |   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) { |   if(data->set.ftp_use_port) { | ||||||
|     bool connected; |     bool connected; | ||||||
|  |  | ||||||
|  |     state(conn, FTP_STOP); /* no longer in STOR state */ | ||||||
|  |  | ||||||
|     result = AllowServerConnect(conn, &connected); |     result = AllowServerConnect(conn, &connected); | ||||||
|     if(result) |     if(result) | ||||||
|       return result; |       return result; | ||||||
| @@ -2450,7 +2440,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct FTP *ftp = data->state.proto.ftp; |   struct FTP *ftp = data->req.protop; | ||||||
|   char *buf = data->state.buffer; |   char *buf = data->state.buffer; | ||||||
|  |  | ||||||
|   if((ftpcode == 150) || (ftpcode == 125)) { |   if((ftpcode == 150) || (ftpcode == 125)) { | ||||||
| @@ -2574,19 +2564,6 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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) { |   if(conn->ssl[FIRSTSOCKET].use) { | ||||||
|     /* PBSZ = PROTECTION BUFFER SIZE. |     /* PBSZ = PROTECTION BUFFER SIZE. | ||||||
|  |  | ||||||
| @@ -2618,7 +2595,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   (void)instate; /* no use for this yet */ |   (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. */ |       /* 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(data->set.krb) { | ||||||
|         /* If not anonymous login, try a secure login. Note that this |         /* If not anonymous login, try a secure login. Note that this | ||||||
|            procedure is still BLOCKING. */ |            procedure is still BLOCKING. */ | ||||||
| @@ -3158,56 +3135,6 @@ static CURLcode ftp_block_statemach(struct connectdata *conn) | |||||||
|   return result; |   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 |  * ftp_connect() should do everything that is to be considered a part of | ||||||
|  * the connection phase. |  * the connection phase. | ||||||
| @@ -3225,14 +3152,6 @@ static CURLcode ftp_connect(struct connectdata *conn, | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to not done yet */ |   *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 */ |   /* We always support persistent connections on ftp */ | ||||||
|   conn->bits.close = FALSE; |   conn->bits.close = FALSE; | ||||||
|  |  | ||||||
| @@ -3272,7 +3191,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, | |||||||
|                               bool premature) |                               bool premature) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   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 ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   struct pingpong *pp = &ftpc->pp; |   struct pingpong *pp = &ftpc->pp; | ||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
| @@ -3689,7 +3608,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) | |||||||
|   bool complete = FALSE; |   bool complete = FALSE; | ||||||
|  |  | ||||||
|   /* the ftp struct is inited in ftp_connect() */ |   /* 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 the second connection isn't done yet, wait for it */ | ||||||
|   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { |   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { | ||||||
| @@ -3837,7 +3756,7 @@ CURLcode ftp_perform(struct connectdata *conn, | |||||||
|  |  | ||||||
|   if(conn->data->set.opt_no_body) { |   if(conn->data->set.opt_no_body) { | ||||||
|     /* requested no body means no transfer... */ |     /* 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; |     ftp->transfer = FTPTRANSFER_INFO; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -4099,17 +4018,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done) | |||||||
|   *done = FALSE; /* default to false */ |   *done = FALSE; /* default to false */ | ||||||
|   ftpc->wait_data_conn = FALSE; /* default to no such wait */ |   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) { |   if(conn->data->set.wildcardmatch) { | ||||||
|     retcode = wc_statemach(conn); |     retcode = wc_statemach(conn); | ||||||
|     if(conn->data->wildcard.state == CURLWC_SKIP || |     if(conn->data->wildcard.state == CURLWC_SKIP || | ||||||
| @@ -4141,7 +4049,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, | |||||||
|   size_t write_len; |   size_t write_len; | ||||||
|   char *sptr=s; |   char *sptr=s; | ||||||
|   CURLcode res = CURLE_OK; |   CURLcode res = CURLE_OK; | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   enum protection_level data_sec = conn->data_prot; |   enum protection_level data_sec = conn->data_prot; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -4161,12 +4069,12 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, | |||||||
|     return(res); |     return(res); | ||||||
|  |  | ||||||
|   for(;;) { |   for(;;) { | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|     conn->data_prot = PROT_CMD; |     conn->data_prot = PROT_CMD; | ||||||
| #endif | #endif | ||||||
|     res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, |     res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, | ||||||
|                      &bytes_written); |                      &bytes_written); | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|     DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); |     DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); | ||||||
|     conn->data_prot = data_sec; |     conn->data_prot = data_sec; | ||||||
| #endif | #endif | ||||||
| @@ -4268,7 +4176,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) | |||||||
|  |  | ||||||
|   Curl_pp_disconnect(pp); |   Curl_pp_disconnect(pp); | ||||||
|  |  | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   Curl_sec_end(conn); |   Curl_sec_end(conn); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -4287,7 +4195,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   /* the ftp struct is already inited in ftp_connect() */ |   /* 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; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   const char *slash_pos;  /* position of the first '/' char in curpos */ |   const char *slash_pos;  /* position of the first '/' char in curpos */ | ||||||
|   const char *path_to_use = data->state.path; |   const char *path_to_use = data->state.path; | ||||||
| @@ -4342,7 +4250,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
|         dirlen++; |         dirlen++; | ||||||
|  |  | ||||||
|       ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/", |       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); |                                          NULL); | ||||||
|       if(!ftpc->dirs[0]) { |       if(!ftpc->dirs[0]) { | ||||||
|         freedirs(ftpc); |         freedirs(ftpc); | ||||||
| @@ -4477,7 +4385,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
| static CURLcode ftp_dophase_done(struct connectdata *conn, | static CURLcode ftp_dophase_done(struct connectdata *conn, | ||||||
|                                  bool connected) |                                  bool connected) | ||||||
| { | { | ||||||
|   struct FTP *ftp = conn->data->state.proto.ftp; |   struct FTP *ftp = conn->data->req.protop; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if(connected) { |   if(connected) { | ||||||
| @@ -4577,6 +4485,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn) | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *type; |   char *type; | ||||||
|   char command; |   char command; | ||||||
|  |   struct FTP *ftp; | ||||||
|  |  | ||||||
|   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { |   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { | ||||||
|     /* Unless we have asked to tunnel ftp operations through the proxy, we |     /* 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; |       return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|     /* |     /* set it up as a HTTP connection instead */ | ||||||
|      * We explicitly mark this connection as persistent here as we're doing |     return conn->handler->setup_connection(conn); | ||||||
|      * FTP over HTTP and thus we accidentally avoid setting this value |  | ||||||
|      * otherwise. |  | ||||||
|      */ |  | ||||||
|     conn->bits.close = FALSE; |  | ||||||
| #else | #else | ||||||
|     failf(data, "FTP over http proxy requires HTTP support built-in!"); |     failf(data, "FTP over http proxy requires HTTP support built-in!"); | ||||||
|     return CURLE_UNSUPPORTED_PROTOCOL; |     return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| #endif | #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.path++;   /* don't include the initial slash */ | ||||||
|   data->state.slash_removed = TRUE; /* we've skipped the 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; |   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); | 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 |  * 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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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) | #if defined(HAVE_GETADDRINFO_THREADSAFE) | ||||||
|   else { |   else { | ||||||
|     struct addrinfo hints; |     struct addrinfo hints; | ||||||
|     char sbuf[NI_MAXSERV]; |     char sbuf[12]; | ||||||
|     char *sbufptr = NULL; |     char *sbufptr = NULL; | ||||||
|  |  | ||||||
|     memset(&hints, 0, sizeof(hints)); |     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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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; |   struct addrinfo hints; | ||||||
|   Curl_addrinfo *res; |   Curl_addrinfo *res; | ||||||
|   int error; |   int error; | ||||||
|   char sbuf[NI_MAXSERV]; |   char sbuf[12]; | ||||||
|   char *sbufptr = NULL; |   char *sbufptr = NULL; | ||||||
|   char addrbuf[128]; |   char addrbuf[128]; | ||||||
|   int pf; |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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 */ | #endif /* truly sync */ | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								lib/http.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								lib/http.c
									
									
									
									
									
								
							| @@ -75,6 +75,7 @@ | |||||||
| #include "non-ascii.h" | #include "non-ascii.h" | ||||||
| #include "bundles.h" | #include "bundles.h" | ||||||
| #include "pipeline.h" | #include "pipeline.h" | ||||||
|  | #include "http2.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn, | |||||||
|  */ |  */ | ||||||
| const struct Curl_handler Curl_handler_http = { | const struct Curl_handler Curl_handler_http = { | ||||||
|   "HTTP",                               /* scheme */ |   "HTTP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = { | |||||||
|  */ |  */ | ||||||
| const struct Curl_handler Curl_handler_https = { | const struct Curl_handler Curl_handler_https = { | ||||||
|   "HTTPS",                              /* scheme */ |   "HTTPS",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = { | |||||||
| #endif | #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 |  * checkheaders() checks the linked list of custom HTTP headers for a | ||||||
|  * particular header (prefix). |  * particular header (prefix). | ||||||
| @@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick) | |||||||
| static CURLcode http_perhapsrewind(struct connectdata *conn) | static CURLcode http_perhapsrewind(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   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 bytessent; | ||||||
|   curl_off_t expectsend = -1; /* default is unknown */ |   curl_off_t expectsend = -1; /* default is unknown */ | ||||||
|  |  | ||||||
| @@ -948,7 +962,7 @@ static size_t readmoredata(char *buffer, | |||||||
|                            void *userp) |                            void *userp) | ||||||
| { | { | ||||||
|   struct connectdata *conn = (struct connectdata *)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; |   size_t fullsize = size * nitems; | ||||||
|  |  | ||||||
|   if(0 == http->postsize) |   if(0 == http->postsize) | ||||||
| @@ -1019,7 +1033,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, | |||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   char *ptr; |   char *ptr; | ||||||
|   size_t size; |   size_t size; | ||||||
|   struct HTTP *http = conn->data->state.proto.http; |   struct HTTP *http = conn->data->req.protop; | ||||||
|   size_t sendsize; |   size_t sendsize; | ||||||
|   curl_socket_t sockfd; |   curl_socket_t sockfd; | ||||||
|   size_t headersize; |   size_t headersize; | ||||||
| @@ -1402,7 +1416,7 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
|                         CURLcode status, bool premature) |                         CURLcode status, bool premature) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct HTTP *http =data->state.proto.http; |   struct HTTP *http =data->req.protop; | ||||||
|  |  | ||||||
|   Curl_unencode_cleanup(conn); |   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 |   if(!premature && /* this check is pointless when DONE is called before the | ||||||
|                       entire operation is complete */ |                       entire operation is complete */ | ||||||
|      !conn->bits.retry && |      !conn->bits.retry && | ||||||
|  |      !data->set.connect_only && | ||||||
|      ((http->readbytecount + |      ((http->readbytecount + | ||||||
|        data->req.headerbytecount - |        data->req.headerbytecount - | ||||||
|        data->req.deductheadercount)) <= 0) { |        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 |  * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons | ||||||
|    connected to only supports 1.0, or if any server previously contacted to |  * to avoid it include: | ||||||
|    handle this request only supports 1.0. */ |  * | ||||||
| static bool use_http_1_1(const struct SessionHandle *data, |  * - 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) |                              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) && |          ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && | ||||||
|           ((conn->httpversion == 11) || |           ((conn->httpversion == 11) || | ||||||
|            ((conn->httpversion != 10) && |            ((conn->httpversion != 10) && | ||||||
| @@ -1479,7 +1499,7 @@ static CURLcode expect100(struct SessionHandle *data, | |||||||
|   const char *ptr; |   const char *ptr; | ||||||
|   data->state.expect100header = FALSE; /* default to false unless it is set |   data->state.expect100header = FALSE; /* default to false unless it is set | ||||||
|                                           to TRUE below */ |                                           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: |     /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: | ||||||
|        100-continue to the headers which actually speeds up post operations |        100-continue to the headers which actually speeds up post operations | ||||||
|        (as there is one packet coming back from the web server) */ |        (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. */ |      the rest of the request in the PERFORM phase. */ | ||||||
|   *done = TRUE; |   *done = TRUE; | ||||||
|  |  | ||||||
|   /* If there already is a protocol-specific struct allocated for this |   http = data->req.protop; | ||||||
|      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; |  | ||||||
|  |  | ||||||
|   if(!data->state.this_is_a_follow) { |   if(!data->state.this_is_a_follow) { | ||||||
|     /* this is not a followed location, get the original host name */ |     /* 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) |       if(conn->bits.authneg) | ||||||
|         /* don't enable chunked during auth neg */ |         /* 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 */ |         /* HTTP, upload, unknown file size and not HTTP 1.0 */ | ||||||
|         data->req.upload_chunky = TRUE; |         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 |   /* Use 1.1 unless the user specifically asked for 1.0 or the server only | ||||||
|      supports 1.0 */ |      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 */ |   /* initialize a dynamic send-buffer */ | ||||||
|   req_buffer = Curl_add_buffer_init(); |   req_buffer = Curl_add_buffer_init(); | ||||||
| @@ -2173,6 +2180,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|   if(result) |   if(result) | ||||||
|     return 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 !defined(CURL_DISABLE_COOKIES) | ||||||
|   if(data->cookies || addcookies) { |   if(data->cookies || addcookies) { | ||||||
|     struct Cookie *co=NULL; /* no cookies from start */ |     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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -21,8 +21,14 @@ | |||||||
|  * KIND, either express or implied. |  * KIND, either express or implied. | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
|  | #include "curl_setup.h" | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_HTTP | #ifndef CURL_DISABLE_HTTP | ||||||
|  |  | ||||||
|  | #ifdef USE_NGHTTP2 | ||||||
|  | #include <nghttp2/nghttp2.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| extern const struct Curl_handler Curl_handler_http; | extern const struct Curl_handler Curl_handler_http; | ||||||
|  |  | ||||||
| #ifdef USE_SSL | #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(struct connectdata *conn, bool *done); | ||||||
| CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); | CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); | ||||||
| CURLcode Curl_http_connect(struct connectdata *conn, bool *done); | 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 */ | /* The following functions are defined in http_chunks.c */ | ||||||
| void Curl_httpchunk_init(struct connectdata *conn); | void Curl_httpchunk_init(struct connectdata *conn); | ||||||
| @@ -141,6 +148,14 @@ struct HTTP { | |||||||
|                         points to an allocated send_buffer struct */ |                         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, | CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, | ||||||
|                                      struct connectdata *conn, |                                      struct connectdata *conn, | ||||||
|                                      ssize_t *nread, |                                      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 |      * This function might be called several times in the multi interface case | ||||||
|      * if the proxy's CONNTECT response is not instant. |      * 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)); |     memset(&http_proxy, 0, sizeof(http_proxy)); | ||||||
|     conn->data->state.proto.http = &http_proxy; |     conn->data->req.protop = &http_proxy; | ||||||
|     conn->bits.close = FALSE; |     conn->bits.close = FALSE; | ||||||
|     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, |     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, | ||||||
|                                conn->host.name, conn->remote_port); |                                conn->host.name, conn->remote_port); | ||||||
|     conn->data->state.proto.generic = prot_save; |     conn->data->req.protop = prot_save; | ||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
| #else | #else | ||||||
|   | |||||||
							
								
								
									
										187
									
								
								lib/imap.c
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								lib/imap.c
									
									
									
									
									
								
							| @@ -26,6 +26,7 @@ | |||||||
|  * RFC4616 PLAIN authentication |  * RFC4616 PLAIN authentication | ||||||
|  * RFC4959 IMAP Extension for SASL Initial Client Response |  * RFC4959 IMAP Extension for SASL Initial Client Response | ||||||
|  * RFC5092 IMAP URL Scheme |  * 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 = { | static const struct Curl_handler Curl_handler_imap_proxy = { | ||||||
|   "IMAP",                               /* scheme */ |   "IMAP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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 = { | static const struct Curl_handler Curl_handler_imaps_proxy = { | ||||||
|   "IMAPS",                              /* scheme */ |   "IMAPS",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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, | static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | ||||||
|                            int *resp) |                            int *resp) | ||||||
| { | { | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   const char *id = imapc->resptag; |   const char *id = imapc->resptag; | ||||||
|   size_t id_len = strlen(id); |   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") || |            (strcmp(imap->custom, "STORE") || | ||||||
|             !imap_matchresp(line, len, "FETCH")) && |             !imap_matchresp(line, len, "FETCH")) && | ||||||
|            strcmp(imap->custom, "SELECT") && |            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; |           return FALSE; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
| @@ -330,7 +336,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|     return TRUE; |     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)) || |   if((len == 3 && !memcmp("+", line, 1)) || | ||||||
|      (len >= 2 && !memcmp("+ ", line, 2))) { |      (len >= 2 && !memcmp("+ ", line, 2))) { | ||||||
|     switch(imapc->state) { |     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_DIGESTMD5_RESP: | ||||||
|       case IMAP_AUTHENTICATE_NTLM: |       case IMAP_AUTHENTICATE_NTLM: | ||||||
|       case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: |       case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: | ||||||
|  |       case IMAP_AUTHENTICATE_XOAUTH2: | ||||||
|       case IMAP_AUTHENTICATE_FINAL: |       case IMAP_AUTHENTICATE_FINAL: | ||||||
|       case IMAP_APPEND: |       case IMAP_APPEND: | ||||||
|         *resp = '+'; |         *resp = '+'; | ||||||
| @@ -385,6 +395,7 @@ static void state(struct connectdata *conn, imapstate newstate) | |||||||
|     "AUTHENTICATE_DIGESTMD5_RESP", |     "AUTHENTICATE_DIGESTMD5_RESP", | ||||||
|     "AUTHENTICATE_NTLM", |     "AUTHENTICATE_NTLM", | ||||||
|     "AUTHENTICATE_NTLM_TYPE2MSG", |     "AUTHENTICATE_NTLM_TYPE2MSG", | ||||||
|  |     "AUTHENTICATE_XOAUTH2", | ||||||
|     "AUTHENTICATE_FINAL", |     "AUTHENTICATE_FINAL", | ||||||
|     "LOGIN", |     "LOGIN", | ||||||
|     "LIST", |     "LIST", | ||||||
| @@ -547,13 +558,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|   if((imapc->authmechs & SASL_MECH_DIGEST_MD5) && |   if((imapc->authmechs & SASL_MECH_DIGEST_MD5) && | ||||||
|      (imapc->prefmech & SASL_MECH_DIGEST_MD5)) { |      (imapc->prefmech & SASL_MECH_DIGEST_MD5)) { | ||||||
|     mech = "DIGEST-MD5"; |     mech = SASL_MECH_STRING_DIGEST_MD5; | ||||||
|     state1 = IMAP_AUTHENTICATE_DIGESTMD5; |     state1 = IMAP_AUTHENTICATE_DIGESTMD5; | ||||||
|     imapc->authused = SASL_MECH_DIGEST_MD5; |     imapc->authused = SASL_MECH_DIGEST_MD5; | ||||||
|   } |   } | ||||||
|   else if((imapc->authmechs & SASL_MECH_CRAM_MD5) && |   else if((imapc->authmechs & SASL_MECH_CRAM_MD5) && | ||||||
|           (imapc->prefmech & SASL_MECH_CRAM_MD5)) { |           (imapc->prefmech & SASL_MECH_CRAM_MD5)) { | ||||||
|     mech = "CRAM-MD5"; |     mech = SASL_MECH_STRING_CRAM_MD5; | ||||||
|     state1 = IMAP_AUTHENTICATE_CRAMMD5; |     state1 = IMAP_AUTHENTICATE_CRAMMD5; | ||||||
|     imapc->authused = SASL_MECH_CRAM_MD5; |     imapc->authused = SASL_MECH_CRAM_MD5; | ||||||
|   } |   } | ||||||
| @@ -562,7 +573,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
| #ifdef USE_NTLM | #ifdef USE_NTLM | ||||||
|     if((imapc->authmechs & SASL_MECH_NTLM) && |     if((imapc->authmechs & SASL_MECH_NTLM) && | ||||||
|        (imapc->prefmech & SASL_MECH_NTLM)) { |        (imapc->prefmech & SASL_MECH_NTLM)) { | ||||||
|     mech = "NTLM"; |     mech = SASL_MECH_STRING_NTLM; | ||||||
|     state1 = IMAP_AUTHENTICATE_NTLM; |     state1 = IMAP_AUTHENTICATE_NTLM; | ||||||
|     state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; |     state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; | ||||||
|     imapc->authused = SASL_MECH_NTLM; |     imapc->authused = SASL_MECH_NTLM; | ||||||
| @@ -574,9 +585,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else |   else | ||||||
| #endif | #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)) { |      (imapc->prefmech & SASL_MECH_LOGIN)) { | ||||||
|     mech = "LOGIN"; |     mech = SASL_MECH_STRING_LOGIN; | ||||||
|     state1 = IMAP_AUTHENTICATE_LOGIN; |     state1 = IMAP_AUTHENTICATE_LOGIN; | ||||||
|     state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; |     state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; | ||||||
|     imapc->authused = SASL_MECH_LOGIN; |     imapc->authused = SASL_MECH_LOGIN; | ||||||
| @@ -587,7 +611,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else if((imapc->authmechs & SASL_MECH_PLAIN) && |   else if((imapc->authmechs & SASL_MECH_PLAIN) && | ||||||
|           (imapc->prefmech & SASL_MECH_PLAIN)) { |           (imapc->prefmech & SASL_MECH_PLAIN)) { | ||||||
|     mech = "PLAIN"; |     mech = SASL_MECH_STRING_PLAIN; | ||||||
|     state1 = IMAP_AUTHENTICATE_PLAIN; |     state1 = IMAP_AUTHENTICATE_PLAIN; | ||||||
|     state2 = IMAP_AUTHENTICATE_FINAL; |     state2 = IMAP_AUTHENTICATE_FINAL; | ||||||
|     imapc->authused = SASL_MECH_PLAIN; |     imapc->authused = SASL_MECH_PLAIN; | ||||||
| @@ -638,7 +662,7 @@ static CURLcode imap_perform_list(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
|   if(imap->custom) |   if(imap->custom) | ||||||
| @@ -673,7 +697,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
| @@ -712,7 +736,7 @@ static CURLcode imap_perform_select(struct connectdata *conn) | |||||||
| static CURLcode imap_perform_fetch(struct connectdata *conn) | static CURLcode imap_perform_fetch(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|  |  | ||||||
|   /* Check we have a UID */ |   /* Check we have a UID */ | ||||||
|   if(!imap->uid) { |   if(!imap->uid) { | ||||||
| @@ -740,7 +764,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn) | |||||||
| static CURLcode imap_perform_append(struct connectdata *conn) | static CURLcode imap_perform_append(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct IMAP *imap = conn->data->state.proto.imap; |   struct IMAP *imap = conn->data->req.protop; | ||||||
|   char *mailbox; |   char *mailbox; | ||||||
|  |  | ||||||
|   /* Check we have a mailbox */ |   /* Check we have a mailbox */ | ||||||
| @@ -864,20 +888,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, | |||||||
|         wordlen -= 5; |         wordlen -= 5; | ||||||
|  |  | ||||||
|         /* Test the word for a matching authentication mechanism */ |         /* 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; |           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; |           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; |           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; |           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; |           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; |           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; |           imapc->authmechs |= SASL_MECH_NTLM; | ||||||
|  |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |           imapc->authmechs |= SASL_MECH_XOAUTH2; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       line += wordlen; |       line += wordlen; | ||||||
| @@ -1243,6 +1269,44 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn, | |||||||
| } | } | ||||||
| #endif | #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 */ | /* For final responses to the AUTHENTICATE sequence */ | ||||||
| static CURLcode imap_state_auth_final_resp(struct connectdata *conn, | static CURLcode imap_state_auth_final_resp(struct connectdata *conn, | ||||||
|                                            int imapcode, |                                            int imapcode, | ||||||
| @@ -1316,7 +1380,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   const char *line = data->state.buffer; |   const char *line = data->state.buffer; | ||||||
|   char tmp[20]; |   char tmp[20]; | ||||||
| @@ -1407,10 +1471,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, | |||||||
|         return result; |         return result; | ||||||
|  |  | ||||||
|       data->req.bytecount += chunk; |       data->req.bytecount += chunk; | ||||||
|       size -= chunk; |  | ||||||
|  |  | ||||||
|       infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU |       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?*/ |       /* Have we used the entire cache or just part of it?*/ | ||||||
|       if(pp->cache_size > chunk) { |       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! */ |       /* The entire data is already transferred! */ | ||||||
|       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); |       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); | ||||||
|     else { |     else { | ||||||
| @@ -1592,6 +1656,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn) | |||||||
|       break; |       break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     case IMAP_AUTHENTICATE_XOAUTH2: | ||||||
|  |       result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|     case IMAP_AUTHENTICATE_FINAL: |     case IMAP_AUTHENTICATE_FINAL: | ||||||
|       result = imap_state_auth_final_resp(conn, imapcode, imapc->state); |       result = imap_state_auth_final_resp(conn, imapcode, imapc->state); | ||||||
|       break; |       break; | ||||||
| @@ -1642,11 +1710,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) | |||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct imap_conn *imapc = &conn->proto.imapc; |   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); |     result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); | ||||||
|   else |     if(result || !imapc->ssldone) | ||||||
|     result = Curl_pp_statemach(&imapc->pp, FALSE); |       return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   result = Curl_pp_statemach(&imapc->pp, FALSE); | ||||||
|   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; |   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| @@ -1669,13 +1739,11 @@ static CURLcode imap_init(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap; | ||||||
|  |  | ||||||
|   if(!imap) { |   imap = data->req.protop = calloc(sizeof(struct IMAP), 1); | ||||||
|     imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1); |  | ||||||
|   if(!imap) |   if(!imap) | ||||||
|     result = CURLE_OUT_OF_MEMORY; |     result = CURLE_OUT_OF_MEMORY; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -1705,15 +1773,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to not done yet */ |   *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 */ |   /* We always support persistent connections in IMAP */ | ||||||
|   conn->bits.close = FALSE; |   conn->bits.close = FALSE; | ||||||
|  |  | ||||||
| @@ -1759,7 +1818,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct IMAP *imap = data->state.proto.imap; |   struct IMAP *imap = data->req.protop; | ||||||
|  |  | ||||||
|   (void)premature; |   (void)premature; | ||||||
|  |  | ||||||
| @@ -1824,7 +1883,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected, | |||||||
|   /* This is IMAP and no proxy */ |   /* This is IMAP and no proxy */ | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   struct imap_conn *imapc = &conn->proto.imapc; | ||||||
|   bool selected = FALSE; |   bool selected = FALSE; | ||||||
|  |  | ||||||
| @@ -1891,15 +1950,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to false */ |   *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 */ |   /* Parse the URL path */ | ||||||
|   result = imap_parse_url_path(conn); |   result = imap_parse_url_path(conn); | ||||||
|   if(result) |   if(result) | ||||||
| @@ -1952,7 +2002,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) | |||||||
| /* Call this when the DO phase has completed */ | /* Call this when the DO phase has completed */ | ||||||
| static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) | 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; |   (void)connected; | ||||||
|  |  | ||||||
| @@ -2018,6 +2068,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   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) { |   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { | ||||||
|     /* Unless we have asked to tunnel IMAP operations through the proxy, we |     /* Unless we have asked to tunnel IMAP operations through the proxy, we | ||||||
|        switch and use HTTP operations only */ |        switch and use HTTP operations only */ | ||||||
| @@ -2033,10 +2088,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn) | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* We explicitly mark this connection as persistent here as we're doing |     /* set it up as an HTTP connection instead */ | ||||||
|        IMAP over HTTP and thus we accidentally avoid setting this value |     return conn->handler->setup_connection(conn); | ||||||
|        otherwise */ |  | ||||||
|     conn->bits.close = FALSE; |  | ||||||
| #else | #else | ||||||
|     failf(data, "IMAP over http proxy requires HTTP support built-in!"); |     failf(data, "IMAP over http proxy requires HTTP support built-in!"); | ||||||
|     return CURLE_UNSUPPORTED_PROTOCOL; |     return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| @@ -2225,18 +2278,20 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) | |||||||
|  |  | ||||||
|       if(strequal(value, "*")) |       if(strequal(value, "*")) | ||||||
|         imapc->prefmech = SASL_AUTH_ANY; |         imapc->prefmech = SASL_AUTH_ANY; | ||||||
|       else if(strequal(value, "LOGIN")) |       else if(strequal(value, SASL_MECH_STRING_LOGIN)) | ||||||
|         imapc->prefmech = SASL_MECH_LOGIN; |         imapc->prefmech = SASL_MECH_LOGIN; | ||||||
|       else if(strequal(value, "PLAIN")) |       else if(strequal(value, SASL_MECH_STRING_PLAIN)) | ||||||
|         imapc->prefmech = SASL_MECH_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; |         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; |         imapc->prefmech = SASL_MECH_DIGEST_MD5; | ||||||
|       else if(strequal(value, "GSSAPI")) |       else if(strequal(value, SASL_MECH_STRING_GSSAPI)) | ||||||
|         imapc->prefmech = SASL_MECH_GSSAPI; |         imapc->prefmech = SASL_MECH_GSSAPI; | ||||||
|       else if(strequal(value, "NTLM")) |       else if(strequal(value, SASL_MECH_STRING_NTLM)) | ||||||
|         imapc->prefmech = SASL_MECH_NTLM; |         imapc->prefmech = SASL_MECH_NTLM; | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |         imapc->prefmech = SASL_MECH_XOAUTH2; | ||||||
|       else |       else | ||||||
|         imapc->prefmech = SASL_AUTH_NONE; |         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() */ |   /* The imap struct is already initialised in imap_connect() */ | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 *begin = data->state.path; | ||||||
|   const char *ptr = begin; |   const char *ptr = begin; | ||||||
|  |  | ||||||
| @@ -2367,7 +2422,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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]; |   const char *custom = data->set.str[STRING_CUSTOMREQUEST]; | ||||||
|  |  | ||||||
|   if(custom) { |   if(custom) { | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ typedef enum { | |||||||
|   IMAP_AUTHENTICATE_DIGESTMD5_RESP, |   IMAP_AUTHENTICATE_DIGESTMD5_RESP, | ||||||
|   IMAP_AUTHENTICATE_NTLM, |   IMAP_AUTHENTICATE_NTLM, | ||||||
|   IMAP_AUTHENTICATE_NTLM_TYPE2MSG, |   IMAP_AUTHENTICATE_NTLM_TYPE2MSG, | ||||||
|  |   IMAP_AUTHENTICATE_XOAUTH2, | ||||||
|   IMAP_AUTHENTICATE_FINAL, |   IMAP_AUTHENTICATE_FINAL, | ||||||
|   IMAP_LOGIN, |   IMAP_LOGIN, | ||||||
|   IMAP_LIST, |   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 | /* 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). |  * (Royal Institute of Technology, Stockholm, Sweden). | ||||||
|  * Copyright (c) 2004 - 2012 Daniel Stenberg |  * Copyright (c) 2004 - 2012 Daniel Stenberg | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
| @@ -51,7 +51,7 @@ | |||||||
| #include "ftp.h" | #include "ftp.h" | ||||||
| #include "curl_gssapi.h" | #include "curl_gssapi.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| #include "krb4.h" | #include "curl_sec.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
| #include "warnless.h" | #include "warnless.h" | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								lib/ldap.c
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								lib/ldap.c
									
									
									
									
									
								
							| @@ -84,6 +84,9 @@ typedef struct { | |||||||
|   int     lud_scope; |   int     lud_scope; | ||||||
|   char   *lud_filter; |   char   *lud_filter; | ||||||
|   char  **lud_exts; |   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; | } CURL_LDAPURLDesc; | ||||||
|  |  | ||||||
| #undef LDAPURLDesc | #undef LDAPURLDesc | ||||||
| @@ -539,19 +542,15 @@ static bool unescape_elements (void *data, LDAPURLDesc *ludp) | |||||||
|   if(ludp->lud_filter) { |   if(ludp->lud_filter) { | ||||||
|     ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL); |     ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL); | ||||||
|     if(!ludp->lud_filter) |     if(!ludp->lud_filter) | ||||||
|        return (FALSE); |        return FALSE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   for(i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) { |   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]) |     if(!ludp->lud_attrs[i]) | ||||||
|       return (FALSE); |       return FALSE; | ||||||
|   } |     ludp->lud_attrs_dups++; | ||||||
|  |  | ||||||
|   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); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(ludp->lud_dn) { |   if(ludp->lud_dn) { | ||||||
| @@ -637,8 +636,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) | |||||||
|  |  | ||||||
|   if(*p && *p != '?') { |   if(*p && *p != '?') { | ||||||
|     ludp->lud_scope = str2scope(p); |     ludp->lud_scope = str2scope(p); | ||||||
|     if(ludp->lud_scope == -1) |     if(ludp->lud_scope == -1) { | ||||||
|       return LDAP_INVALID_SYNTAX; |       return LDAP_INVALID_SYNTAX; | ||||||
|  |     } | ||||||
|     LDAP_TRACE (("scope %d\n", ludp->lud_scope)); |     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, '?'); |   q = strchr(p, '?'); | ||||||
|   if(q) |   if(q) | ||||||
|     *q++ = '\0'; |     *q++ = '\0'; | ||||||
|   if(!*p) |   if(!*p) { | ||||||
|     return LDAP_INVALID_SYNTAX; |     return LDAP_INVALID_SYNTAX; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   ludp->lud_filter = p; |   ludp->lud_filter = p; | ||||||
|   LDAP_TRACE (("filter '%s'\n", ludp->lud_filter)); |   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: |   success: | ||||||
|   if(!unescape_elements(conn->data, ludp)) |   if(!unescape_elements(conn->data, ludp)) | ||||||
|     return LDAP_NO_MEMORY; |     return LDAP_NO_MEMORY; | ||||||
| @@ -697,7 +685,7 @@ static int _ldap_url_parse (const struct connectdata *conn, | |||||||
|  |  | ||||||
| static void _ldap_free_urldesc (LDAPURLDesc *ludp) | static void _ldap_free_urldesc (LDAPURLDesc *ludp) | ||||||
| { | { | ||||||
|   int i; |   size_t i; | ||||||
|  |  | ||||||
|   if(!ludp) |   if(!ludp) | ||||||
|     return; |     return; | ||||||
| @@ -709,16 +697,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp) | |||||||
|     free(ludp->lud_filter); |     free(ludp->lud_filter); | ||||||
|  |  | ||||||
|   if(ludp->lud_attrs) { |   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[i]); | ||||||
|     free(ludp->lud_attrs); |     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); |   free (ludp); | ||||||
| } | } | ||||||
| #endif  /* !HAVE_LDAP_URL_PARSE */ | #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 |  * 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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -50,15 +50,18 @@ enum host_lookup_state { | |||||||
|  |  | ||||||
| /* | /* | ||||||
|  * @unittest: 1304 |  * @unittest: 1304 | ||||||
|  |  * | ||||||
|  |  * *loginp and *passwordp MUST be allocated if they aren't NULL when passed | ||||||
|  |  * in. | ||||||
|  */ |  */ | ||||||
| int Curl_parsenetrc(const char *host, | int Curl_parsenetrc(const char *host, | ||||||
|                     char *login, |                     char **loginp, | ||||||
|                     char *password, |                     char **passwordp, | ||||||
|                     char *netrcfile) |                     char *netrcfile) | ||||||
| { | { | ||||||
|   FILE *file; |   FILE *file; | ||||||
|   int retcode=1; |   int retcode=1; | ||||||
|   int specific_login = (login[0] != 0); |   int specific_login = (**loginp != 0); | ||||||
|   char *home = NULL; |   char *home = NULL; | ||||||
|   bool home_alloc = FALSE; |   bool home_alloc = FALSE; | ||||||
|   bool netrc_alloc = FALSE; |   bool netrc_alloc = FALSE; | ||||||
| @@ -109,7 +112,7 @@ int Curl_parsenetrc(const char *host, | |||||||
|       tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); |       tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); | ||||||
|       while(!done && tok) { |       while(!done && tok) { | ||||||
|  |  | ||||||
|         if(login[0] && password[0]) { |         if(**loginp && **passwordp) { | ||||||
|           done=TRUE; |           done=TRUE; | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
| @@ -138,16 +141,22 @@ int Curl_parsenetrc(const char *host, | |||||||
|           /* we are now parsing sub-keywords concerning "our" host */ |           /* we are now parsing sub-keywords concerning "our" host */ | ||||||
|           if(state_login) { |           if(state_login) { | ||||||
|             if(specific_login) { |             if(specific_login) { | ||||||
|               state_our_login = Curl_raw_equal(login, tok); |               state_our_login = Curl_raw_equal(*loginp, tok); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|               strncpy(login, tok, LOGINSIZE-1); |               free(*loginp); | ||||||
|  |               *loginp = strdup(tok); | ||||||
|  |               if(!*loginp) | ||||||
|  |                 return -1; /* allocation failed */ | ||||||
|             } |             } | ||||||
|             state_login=0; |             state_login=0; | ||||||
|           } |           } | ||||||
|           else if(state_password) { |           else if(state_password) { | ||||||
|             if(state_our_login || !specific_login) { |             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; |             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 */ | /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ | ||||||
| int Curl_parsenetrc(const char *host, | int Curl_parsenetrc(const char *host, | ||||||
|                     char *login, |                     char **loginp, | ||||||
|                     char *password, |                     char **passwordp, | ||||||
|                     char *filename); |                     char *filename); | ||||||
|   /* Assume: password[0]=0, host[0] != 0. |   /* Assume: (*passwordp)[0]=0, host[0] != 0. | ||||||
|    * If login[0] = 0, search for login and password within a machine section |    * If (*loginp)[0] = 0, search for login and password within a machine | ||||||
|    * in the netrc. |    * section in the netrc. | ||||||
|    * If login[0] != 0, search for password within machine and login. |    * If (*loginp)[0] != 0, search for password within machine and login. | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
| #endif /* HEADER_CURL_NETRC_H */ | #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) | int Curl_nss_seed(struct SessionHandle *data) | ||||||
| { | { | ||||||
|   /* TODO: implement? */ |   /* make sure that NSS is initialized */ | ||||||
|   (void) data; |   return !!Curl_nss_force_init(data); | ||||||
|   return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void Curl_nss_random(struct SessionHandle *data, | void Curl_nss_random(struct SessionHandle *data, | ||||||
| @@ -1553,7 +1552,11 @@ void Curl_nss_random(struct SessionHandle *data, | |||||||
|                      size_t length) |                      size_t length) | ||||||
| { | { | ||||||
|   Curl_nss_seed(data);  /* Initiate the seed if not already done */ |   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 */ | void Curl_nss_md5sum(unsigned char *tmp, /* input */ | ||||||
|   | |||||||
| @@ -378,7 +378,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) | |||||||
|   if(!lr) |   if(!lr) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   lr->msgid = msgid; |   lr->msgid = msgid; | ||||||
|   data->state.proto.generic = lr; |   data->req.protop = lr; | ||||||
|   Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); |   Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); | ||||||
|   *done = TRUE; |   *done = TRUE; | ||||||
|   return CURLE_OK; |   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, | static CURLcode ldap_done(struct connectdata *conn, CURLcode res, | ||||||
|                           bool premature) |                           bool premature) | ||||||
| { | { | ||||||
|   ldapreqinfo *lr = conn->data->state.proto.generic; |   ldapreqinfo *lr = conn->data->req.protop; | ||||||
|   (void)res; |   (void)res; | ||||||
|   (void)premature; |   (void)premature; | ||||||
|  |  | ||||||
| @@ -398,7 +398,7 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res, | |||||||
|       ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); |       ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); | ||||||
|       lr->msgid = 0; |       lr->msgid = 0; | ||||||
|     } |     } | ||||||
|     conn->data->state.proto.generic = NULL; |     conn->data->req.protop = NULL; | ||||||
|     free(lr); |     free(lr); | ||||||
|   } |   } | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| @@ -409,7 +409,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, | |||||||
| { | { | ||||||
|   ldapconninfo *li = conn->proto.generic; |   ldapconninfo *li = conn->proto.generic; | ||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
|   ldapreqinfo *lr = data->state.proto.generic; |   ldapreqinfo *lr = data->req.protop; | ||||||
|   int rc, ret; |   int rc, ret; | ||||||
|   LDAPMessage *result = NULL; |   LDAPMessage *result = NULL; | ||||||
|   LDAPMessage *ent; |   LDAPMessage *ent; | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
| #include "pingpong.h" | #include "pingpong.h" | ||||||
| #include "multiif.h" | #include "multiif.h" | ||||||
| #include "non-ascii.h" | #include "non-ascii.h" | ||||||
|  | #include "sslgen.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -105,6 +106,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) | |||||||
|   if(Curl_pp_moredata(pp)) |   if(Curl_pp_moredata(pp)) | ||||||
|     /* We are receiving and there is data in the cache so just read it */ |     /* We are receiving and there is data in the cache so just read it */ | ||||||
|     rc = 1; |     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 |   else | ||||||
|     rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ |     rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ | ||||||
|                            pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ |                            pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ | ||||||
| @@ -165,7 +169,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, | |||||||
|   struct connectdata *conn = pp->conn; |   struct connectdata *conn = pp->conn; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   enum protection_level data_sec = conn->data_prot; |   enum protection_level data_sec = conn->data_prot; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -194,12 +198,12 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, | |||||||
|     return error; |     return error; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   conn->data_prot = PROT_CMD; |   conn->data_prot = PROT_CMD; | ||||||
| #endif | #endif | ||||||
|   error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, |   error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, | ||||||
|                      &bytes_written); |                      &bytes_written); | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); |   DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); | ||||||
|   conn->data_prot = data_sec; |   conn->data_prot = data_sec; | ||||||
| #endif | #endif | ||||||
| @@ -302,14 +306,14 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, | |||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       int res; |       int res; | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|       enum protection_level prot = conn->data_prot; |       enum protection_level prot = conn->data_prot; | ||||||
|       conn->data_prot = PROT_CLEAR; |       conn->data_prot = PROT_CLEAR; | ||||||
| #endif | #endif | ||||||
|       DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); |       DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); | ||||||
|       res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, |       res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, | ||||||
|                       &gotbytes); |                       &gotbytes); | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|       DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST); |       DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST); | ||||||
|       conn->data_prot = prot; |       conn->data_prot = prot; | ||||||
| #endif | #endif | ||||||
| @@ -352,7 +356,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, | |||||||
|              the line isn't really terminated until the LF comes */ |              the line isn't really terminated until the LF comes */ | ||||||
|  |  | ||||||
|           /* output debug output if that is requested */ |           /* output debug output if that is requested */ | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|           if(!conn->sec_complete) |           if(!conn->sec_complete) | ||||||
| #endif | #endif | ||||||
|             if(data->set.verbose) |             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)) { |           if(pp->endofresp(conn, pp->linestart_resp, perline, code)) { | ||||||
|             /* This is the end of the last line, copy the last line to the |             /* 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 |                start of the buffer and zero terminate, for old times sake */ | ||||||
|                krb4)! */ |  | ||||||
|             char *meow; |             char *meow; | ||||||
|             int n; |             int n; | ||||||
|             for(meow=pp->linestart_resp, n=0; meow<ptr; meow++, 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) |  * RFC4422 Simple Authentication and Security Layer (SASL) | ||||||
|  * RFC4616 PLAIN authentication |  * RFC4616 PLAIN authentication | ||||||
|  * RFC5034 POP3 SASL Authentication Mechanism |  * 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 = { | static const struct Curl_handler Curl_handler_pop3_proxy = { | ||||||
|   "POP3",                               /* scheme */ |   "POP3",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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 = { | static const struct Curl_handler Curl_handler_pop3s_proxy = { | ||||||
|   "POP3S",                              /* scheme */ |   "POP3S",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -312,20 +313,22 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|           wordlen++; |           wordlen++; | ||||||
|  |  | ||||||
|         /* Test the word for a matching authentication mechanism */ |         /* 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; |           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; |           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; |           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; |           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; |           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; |           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; |           pop3c->authmechs |= SASL_MECH_NTLM; | ||||||
|  |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |           pop3c->authmechs |= SASL_MECH_XOAUTH2; | ||||||
|  |  | ||||||
|         line += wordlen; |         line += wordlen; | ||||||
|         len -= wordlen; |         len -= wordlen; | ||||||
| @@ -371,6 +374,7 @@ static void state(struct connectdata *conn, pop3state newstate) | |||||||
|     "AUTH_DIGESTMD5_RESP", |     "AUTH_DIGESTMD5_RESP", | ||||||
|     "AUTH_NTLM", |     "AUTH_NTLM", | ||||||
|     "AUTH_NTLM_TYPE2MSG", |     "AUTH_NTLM_TYPE2MSG", | ||||||
|  |     "AUTH_XOAUTH2", | ||||||
|     "AUTH_FINAL", |     "AUTH_FINAL", | ||||||
|     "APOP", |     "APOP", | ||||||
|     "USER", |     "USER", | ||||||
| @@ -572,13 +576,13 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn) | |||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|     if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) && |     if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) && | ||||||
|        (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) { |        (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) { | ||||||
|       mech = "DIGEST-MD5"; |       mech = SASL_MECH_STRING_DIGEST_MD5; | ||||||
|       state1 = POP3_AUTH_DIGESTMD5; |       state1 = POP3_AUTH_DIGESTMD5; | ||||||
|       pop3c->authused = SASL_MECH_DIGEST_MD5; |       pop3c->authused = SASL_MECH_DIGEST_MD5; | ||||||
|     } |     } | ||||||
|     else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) && |     else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) && | ||||||
|             (pop3c->prefmech & SASL_MECH_CRAM_MD5)) { |             (pop3c->prefmech & SASL_MECH_CRAM_MD5)) { | ||||||
|       mech = "CRAM-MD5"; |       mech = SASL_MECH_STRING_CRAM_MD5; | ||||||
|       state1 = POP3_AUTH_CRAMMD5; |       state1 = POP3_AUTH_CRAMMD5; | ||||||
|       pop3c->authused = SASL_MECH_CRAM_MD5; |       pop3c->authused = SASL_MECH_CRAM_MD5; | ||||||
|     } |     } | ||||||
| @@ -587,7 +591,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn) | |||||||
| #ifdef USE_NTLM | #ifdef USE_NTLM | ||||||
|     if((pop3c->authmechs & SASL_MECH_NTLM) && |     if((pop3c->authmechs & SASL_MECH_NTLM) && | ||||||
|        (pop3c->prefmech & SASL_MECH_NTLM)) { |        (pop3c->prefmech & SASL_MECH_NTLM)) { | ||||||
|       mech = "NTLM"; |       mech = SASL_MECH_STRING_NTLM; | ||||||
|       state1 = POP3_AUTH_NTLM; |       state1 = POP3_AUTH_NTLM; | ||||||
|       state2 = POP3_AUTH_NTLM_TYPE2MSG; |       state2 = POP3_AUTH_NTLM_TYPE2MSG; | ||||||
|       pop3c->authused = SASL_MECH_NTLM; |       pop3c->authused = SASL_MECH_NTLM; | ||||||
| @@ -599,9 +603,22 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|     else |     else | ||||||
| #endif | #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)) { |        (pop3c->prefmech & SASL_MECH_LOGIN)) { | ||||||
|       mech = "LOGIN"; |       mech = SASL_MECH_STRING_LOGIN; | ||||||
|       state1 = POP3_AUTH_LOGIN; |       state1 = POP3_AUTH_LOGIN; | ||||||
|       state2 = POP3_AUTH_LOGIN_PASSWD; |       state2 = POP3_AUTH_LOGIN_PASSWD; | ||||||
|       pop3c->authused = SASL_MECH_LOGIN; |       pop3c->authused = SASL_MECH_LOGIN; | ||||||
| @@ -612,7 +629,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|     else if((pop3c->authmechs & SASL_MECH_PLAIN) && |     else if((pop3c->authmechs & SASL_MECH_PLAIN) && | ||||||
|             (pop3c->prefmech & SASL_MECH_PLAIN)) { |             (pop3c->prefmech & SASL_MECH_PLAIN)) { | ||||||
|       mech = "PLAIN"; |       mech = SASL_MECH_STRING_PLAIN; | ||||||
|       state1 = POP3_AUTH_PLAIN; |       state1 = POP3_AUTH_PLAIN; | ||||||
|       state2 = POP3_AUTH_FINAL; |       state2 = POP3_AUTH_FINAL; | ||||||
|       pop3c->authused = SASL_MECH_PLAIN; |       pop3c->authused = SASL_MECH_PLAIN; | ||||||
| @@ -673,7 +690,7 @@ static CURLcode pop3_perform_command(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct POP3 *pop3 = data->state.proto.pop3; |   struct POP3 *pop3 = data->req.protop; | ||||||
|   const char *command = NULL; |   const char *command = NULL; | ||||||
|  |  | ||||||
|   /* Calculate the default command */ |   /* Calculate the default command */ | ||||||
| @@ -1110,6 +1127,43 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn, | |||||||
| } | } | ||||||
| #endif | #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 */ | /* For final responses to the AUTH sequence */ | ||||||
| static CURLcode pop3_state_auth_final_resp(struct connectdata *conn, | static CURLcode pop3_state_auth_final_resp(struct connectdata *conn, | ||||||
|                                            int pop3code, |                                            int pop3code, | ||||||
| @@ -1203,7 +1257,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 pop3_conn *pop3c = &conn->proto.pop3c; | ||||||
|   struct pingpong *pp = &pop3c->pp; |   struct pingpong *pp = &pop3c->pp; | ||||||
|  |  | ||||||
| @@ -1328,6 +1382,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn) | |||||||
|       break; |       break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     case POP3_AUTH_XOAUTH2: | ||||||
|  |       result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|     case POP3_AUTH_FINAL: |     case POP3_AUTH_FINAL: | ||||||
|       result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state); |       result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state); | ||||||
|       break; |       break; | ||||||
| @@ -1368,11 +1426,13 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) | |||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct pop3_conn *pop3c = &conn->proto.pop3c; |   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); |     result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); | ||||||
|   else |     if(result || !pop3c->ssldone) | ||||||
|     result = Curl_pp_statemach(&pop3c->pp, FALSE); |       return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   result = Curl_pp_statemach(&pop3c->pp, FALSE); | ||||||
|   *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; |   *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| @@ -1395,13 +1455,11 @@ static CURLcode pop3_init(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct POP3 *pop3 = data->state.proto.pop3; |   struct POP3 *pop3; | ||||||
|  |  | ||||||
|   if(!pop3) { |   pop3 = data->req.protop = calloc(sizeof(struct POP3), 1); | ||||||
|     pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1); |  | ||||||
|   if(!pop3) |   if(!pop3) | ||||||
|     result = CURLE_OUT_OF_MEMORY; |     result = CURLE_OUT_OF_MEMORY; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -1431,15 +1489,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to not done yet */ |   *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 */ |   /* We always support persistent connections in POP3 */ | ||||||
|   conn->bits.close = FALSE; |   conn->bits.close = FALSE; | ||||||
|  |  | ||||||
| @@ -1483,7 +1532,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct POP3 *pop3 = data->state.proto.pop3; |   struct POP3 *pop3 = data->req.protop; | ||||||
|  |  | ||||||
|   (void)premature; |   (void)premature; | ||||||
|  |  | ||||||
| @@ -1526,7 +1575,7 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected, | |||||||
|  |  | ||||||
|   if(conn->data->set.opt_no_body) { |   if(conn->data->set.opt_no_body) { | ||||||
|     /* Requested no body means no transfer */ |     /* 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; |     pop3->transfer = FTPTRANSFER_INFO; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -1563,15 +1612,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to false */ |   *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 */ |   /* Parse the URL path */ | ||||||
|   result = pop3_parse_url_path(conn); |   result = pop3_parse_url_path(conn); | ||||||
|   if(result) |   if(result) | ||||||
| @@ -1685,6 +1725,11 @@ static CURLcode pop3_setup_connection(struct connectdata *conn) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   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) { |   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { | ||||||
|     /* Unless we have asked to tunnel POP3 operations through the proxy, we |     /* Unless we have asked to tunnel POP3 operations through the proxy, we | ||||||
|        switch and use HTTP operations only */ |        switch and use HTTP operations only */ | ||||||
| @@ -1700,10 +1745,8 @@ static CURLcode pop3_setup_connection(struct connectdata *conn) | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* We explicitly mark this connection as persistent here as we're doing |     /* set it up as an HTTP connection instead */ | ||||||
|        POP3 over HTTP and thus we accidentally avoid setting this value |     return conn->handler->setup_connection(conn); | ||||||
|        otherwise */ |  | ||||||
|     conn->bits.close = FALSE; |  | ||||||
| #else | #else | ||||||
|     failf(data, "POP3 over http proxy requires HTTP support built-in!"); |     failf(data, "POP3 over http proxy requires HTTP support built-in!"); | ||||||
|     return CURLE_UNSUPPORTED_PROTOCOL; |     return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| @@ -1745,30 +1788,34 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn) | |||||||
|         pop3c->preftype = POP3_TYPE_APOP; |         pop3c->preftype = POP3_TYPE_APOP; | ||||||
|         pop3c->prefmech = SASL_AUTH_NONE; |         pop3c->prefmech = SASL_AUTH_NONE; | ||||||
|       } |       } | ||||||
|       else if(strequal(value, "LOGIN")) { |       else if(strequal(value, SASL_MECH_STRING_LOGIN)) { | ||||||
|         pop3c->preftype = POP3_TYPE_SASL; |         pop3c->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_LOGIN; |         pop3c->prefmech = SASL_MECH_LOGIN; | ||||||
|       } |       } | ||||||
|       else if(strequal(value, "PLAIN")) { |       else if(strequal(value, SASL_MECH_STRING_PLAIN)) { | ||||||
|         pop3c->preftype = POP3_TYPE_SASL; |         pop3c->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_PLAIN; |         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->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_CRAM_MD5; |         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->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_DIGEST_MD5; |         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->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_GSSAPI; |         pop3c->prefmech = SASL_MECH_GSSAPI; | ||||||
|       } |       } | ||||||
|       else if(strequal(value, "NTLM")) { |       else if(strequal(value, SASL_MECH_STRING_NTLM)) { | ||||||
|         pop3c->preftype = POP3_TYPE_SASL; |         pop3c->preftype = POP3_TYPE_SASL; | ||||||
|         pop3c->prefmech = SASL_MECH_NTLM; |         pop3c->prefmech = SASL_MECH_NTLM; | ||||||
|       } |       } | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) { | ||||||
|  |         pop3c->preftype = POP3_TYPE_SASL; | ||||||
|  |         pop3c->prefmech = SASL_MECH_XOAUTH2; | ||||||
|  |       } | ||||||
|       else { |       else { | ||||||
|         pop3c->preftype = POP3_TYPE_NONE; |         pop3c->preftype = POP3_TYPE_NONE; | ||||||
|         pop3c->prefmech = SASL_AUTH_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() */ |   /* The POP3 struct is already initialised in pop3_connect() */ | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct POP3 *pop3 = data->state.proto.pop3; |   struct POP3 *pop3 = data->req.protop; | ||||||
|   const char *path = data->state.path; |   const char *path = data->state.path; | ||||||
|  |  | ||||||
|   /* URL decode the path for the message ID */ |   /* 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; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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]; |   const char *custom = data->set.str[STRING_CUSTOMREQUEST]; | ||||||
|  |  | ||||||
|   /* URL decode the custom request */ |   /* URL decode the custom request */ | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ typedef enum { | |||||||
|   POP3_AUTH_DIGESTMD5_RESP, |   POP3_AUTH_DIGESTMD5_RESP, | ||||||
|   POP3_AUTH_NTLM, |   POP3_AUTH_NTLM, | ||||||
|   POP3_AUTH_NTLM_TYPE2MSG, |   POP3_AUTH_NTLM_TYPE2MSG, | ||||||
|  |   POP3_AUTH_XOAUTH2, | ||||||
|   POP3_AUTH_FINAL, |   POP3_AUTH_FINAL, | ||||||
|   POP3_APOP, |   POP3_APOP, | ||||||
|   POP3_USER, |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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, |                                    ssize_t *nread, | ||||||
|                                    bool *readmore); |                                    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 | /* 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 |    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 = { | const struct Curl_handler Curl_handler_rtsp = { | ||||||
|   "RTSP",                               /* scheme */ |   "RTSP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   rtsp_setup_connection,                /* setup_connection */ | ||||||
|   rtsp_do,                              /* do_it */ |   rtsp_do,                              /* do_it */ | ||||||
|   rtsp_done,                            /* done */ |   rtsp_done,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -122,6 +124,19 @@ const struct Curl_handler Curl_handler_rtsp = { | |||||||
|   PROTOPT_NONE                          /* flags */ |   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 |  * 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, |  * 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) |                           CURLcode status, bool premature) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct RTSP *rtsp = data->state.proto.rtsp; |   struct RTSP *rtsp = data->req.protop; | ||||||
|   CURLcode httpStatus; |   CURLcode httpStatus; | ||||||
|   long CSeq_sent; |   long CSeq_sent; | ||||||
|   long CSeq_recv; |   long CSeq_recv; | ||||||
| @@ -221,7 +236,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   CURLcode result=CURLE_OK; |   CURLcode result=CURLE_OK; | ||||||
|   Curl_RtspReq rtspreq = data->set.rtspreq; |   Curl_RtspReq rtspreq = data->set.rtspreq; | ||||||
|   struct RTSP *rtsp; |   struct RTSP *rtsp = data->req.protop; | ||||||
|   struct HTTP *http; |   struct HTTP *http; | ||||||
|   Curl_send_buffer *req_buffer; |   Curl_send_buffer *req_buffer; | ||||||
|   curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ |   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; |   *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); |   http = &(rtsp->http_wrapper); | ||||||
|   /* Assert that no one has changed the RTSP struct in an evil way */ |   /* Assert that no one has changed the RTSP struct in an evil way */ | ||||||
|   DEBUGASSERT((void *)http == (void *)rtsp); |   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 */ |     /* Store the received CSeq. Match is verified in rtsp_done */ | ||||||
|     int nc = sscanf(&header[4], ": %ld", &CSeq); |     int nc = sscanf(&header[4], ": %ld", &CSeq); | ||||||
|     if(nc == 1) { |     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 */ |       data->state.rtsp_CSeq_recv = CSeq; /* update the handle */ | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  * rewrite to work around the paragraph 2 in the BSD licenses as explained |  * rewrite to work around the paragraph 2 in the BSD licenses as explained | ||||||
|  * below. |  * below. | ||||||
|  * |  * | ||||||
|  * Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan |  * Copyright (c) 1998, 1999, 2013 Kungliga Tekniska H<>gskolan | ||||||
|  * (Royal Institute of Technology, Stockholm, Sweden). |  * (Royal Institute of Technology, Stockholm, Sweden). | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| @@ -44,7 +44,7 @@ | |||||||
| #include "curl_setup.h" | #include "curl_setup.h" | ||||||
|  |  | ||||||
| #ifndef CURL_DISABLE_FTP | #ifndef CURL_DISABLE_FTP | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|  |  | ||||||
| #ifdef HAVE_NETDB_H | #ifdef HAVE_NETDB_H | ||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
| @@ -57,7 +57,7 @@ | |||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include "curl_base64.h" | #include "curl_base64.h" | ||||||
| #include "curl_memory.h" | #include "curl_memory.h" | ||||||
| #include "krb4.h" | #include "curl_sec.h" | ||||||
| #include "ftp.h" | #include "ftp.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| #include "rawstr.h" | #include "rawstr.h" | ||||||
| @@ -110,11 +110,8 @@ static char level_to_char(int level) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static const struct Curl_sec_client_mech * const mechs[] = { | static const struct Curl_sec_client_mech * const mechs[] = { | ||||||
| #if defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   &Curl_krb5_client_mech, |   &Curl_krb5_client_mech, | ||||||
| #endif |  | ||||||
| #if defined(HAVE_KRB4) |  | ||||||
|   &Curl_krb4_client_mech, |  | ||||||
| #endif | #endif | ||||||
|   NULL |   NULL | ||||||
| }; | }; | ||||||
| @@ -199,7 +196,7 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, | |||||||
|  |  | ||||||
| static CURLcode read_data(struct connectdata *conn, | static CURLcode read_data(struct connectdata *conn, | ||||||
|                           curl_socket_t fd, |                           curl_socket_t fd, | ||||||
|                           struct krb4buffer *buf) |                           struct krb5buffer *buf) | ||||||
| { | { | ||||||
|   int len; |   int len; | ||||||
|   void* tmp; |   void* tmp; | ||||||
| @@ -225,7 +222,7 @@ static CURLcode read_data(struct connectdata *conn, | |||||||
| } | } | ||||||
|  |  | ||||||
| static size_t | 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) |   if(buf->size - buf->index < len) | ||||||
|     len = buf->size - buf->index; |     len = buf->size - buf->index; | ||||||
| @@ -599,6 +596,6 @@ Curl_sec_end(struct connectdata *conn) | |||||||
|   conn->mech = NULL; |   conn->mech = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif /* HAVE_KRB4 || HAVE_GSSAPI */ | #endif /* HAVE_GSSAPI */ | ||||||
|  |  | ||||||
| #endif /* CURL_DISABLE_FTP */ | #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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -35,14 +35,6 @@ | |||||||
| #define _MPRINTF_REPLACE /* use the internal *printf() functions */ | #define _MPRINTF_REPLACE /* use the internal *printf() functions */ | ||||||
| #include <curl/mprintf.h> | #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 "curl_memory.h" | ||||||
| #include "strerror.h" | #include "strerror.h" | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										160
									
								
								lib/smtp.c
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								lib/smtp.c
									
									
									
									
									
								
							| @@ -26,6 +26,7 @@ | |||||||
|  * RFC4616 PLAIN authentication |  * RFC4616 PLAIN authentication | ||||||
|  * RFC4954 SMTP Authentication |  * RFC4954 SMTP Authentication | ||||||
|  * RFC5321 SMTP protocol |  * RFC5321 SMTP protocol | ||||||
|  |  * RFC6749 OAuth 2.0 Authorization Framework | ||||||
|  * Draft   SMTP URL Interface |  * Draft   SMTP URL Interface | ||||||
|  * |  * | ||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
| @@ -161,7 +162,7 @@ const struct Curl_handler Curl_handler_smtps = { | |||||||
|  |  | ||||||
| static const struct Curl_handler Curl_handler_smtp_proxy = { | static const struct Curl_handler Curl_handler_smtp_proxy = { | ||||||
|   "SMTP",                               /* scheme */ |   "SMTP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   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 = { | static const struct Curl_handler Curl_handler_smtps_proxy = { | ||||||
|   "SMTPS",                              /* scheme */ |   "SMTPS",                              /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   Curl_http_setup_conn,                 /* setup_connection */ | ||||||
|   Curl_http,                            /* do_it */ |   Curl_http,                            /* do_it */ | ||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -276,20 +277,22 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, | |||||||
|           wordlen++; |           wordlen++; | ||||||
|  |  | ||||||
|         /* Test the word for a matching authentication mechanism */ |         /* 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; |           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; |           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; |           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; |           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; |           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; |           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; |           smtpc->authmechs |= SASL_MECH_NTLM; | ||||||
|  |         else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |           smtpc->authmechs |= SASL_MECH_XOAUTH2; | ||||||
|  |  | ||||||
|         line += wordlen; |         line += wordlen; | ||||||
|         len -= wordlen; |         len -= wordlen; | ||||||
| @@ -326,6 +329,7 @@ static void state(struct connectdata *conn, smtpstate newstate) | |||||||
|     "AUTH_DIGESTMD5_RESP", |     "AUTH_DIGESTMD5_RESP", | ||||||
|     "AUTH_NTLM", |     "AUTH_NTLM", | ||||||
|     "AUTH_NTLM_TYPE2MSG", |     "AUTH_NTLM_TYPE2MSG", | ||||||
|  |     "AUTH_XOAUTH2", | ||||||
|     "AUTH_FINAL", |     "AUTH_FINAL", | ||||||
|     "MAIL", |     "MAIL", | ||||||
|     "RCPT", |     "RCPT", | ||||||
| @@ -469,13 +473,13 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn) | |||||||
| #ifndef CURL_DISABLE_CRYPTO_AUTH | #ifndef CURL_DISABLE_CRYPTO_AUTH | ||||||
|   if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) && |   if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) && | ||||||
|      (smtpc->prefmech & SASL_MECH_DIGEST_MD5)) { |      (smtpc->prefmech & SASL_MECH_DIGEST_MD5)) { | ||||||
|     mech = "DIGEST-MD5"; |     mech = SASL_MECH_STRING_DIGEST_MD5; | ||||||
|     state1 = SMTP_AUTH_DIGESTMD5; |     state1 = SMTP_AUTH_DIGESTMD5; | ||||||
|     smtpc->authused = SASL_MECH_DIGEST_MD5; |     smtpc->authused = SASL_MECH_DIGEST_MD5; | ||||||
|   } |   } | ||||||
|   else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) && |   else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) && | ||||||
|           (smtpc->prefmech & SASL_MECH_CRAM_MD5)) { |           (smtpc->prefmech & SASL_MECH_CRAM_MD5)) { | ||||||
|     mech = "CRAM-MD5"; |     mech = SASL_MECH_STRING_CRAM_MD5; | ||||||
|     state1 = SMTP_AUTH_CRAMMD5; |     state1 = SMTP_AUTH_CRAMMD5; | ||||||
|     smtpc->authused = SASL_MECH_CRAM_MD5; |     smtpc->authused = SASL_MECH_CRAM_MD5; | ||||||
|   } |   } | ||||||
| @@ -484,7 +488,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn) | |||||||
| #ifdef USE_NTLM | #ifdef USE_NTLM | ||||||
|   if((smtpc->authmechs & SASL_MECH_NTLM) && |   if((smtpc->authmechs & SASL_MECH_NTLM) && | ||||||
|      (smtpc->prefmech & SASL_MECH_NTLM)) { |      (smtpc->prefmech & SASL_MECH_NTLM)) { | ||||||
|     mech = "NTLM"; |     mech = SASL_MECH_STRING_NTLM; | ||||||
|     state1 = SMTP_AUTH_NTLM; |     state1 = SMTP_AUTH_NTLM; | ||||||
|     state2 = SMTP_AUTH_NTLM_TYPE2MSG; |     state2 = SMTP_AUTH_NTLM_TYPE2MSG; | ||||||
|     smtpc->authused = SASL_MECH_NTLM; |     smtpc->authused = SASL_MECH_NTLM; | ||||||
| @@ -496,9 +500,22 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|   else |   else | ||||||
| #endif | #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)) { |      (smtpc->prefmech & SASL_MECH_LOGIN)) { | ||||||
|     mech = "LOGIN"; |     mech = SASL_MECH_STRING_LOGIN; | ||||||
|     state1 = SMTP_AUTH_LOGIN; |     state1 = SMTP_AUTH_LOGIN; | ||||||
|     state2 = SMTP_AUTH_LOGIN_PASSWD; |     state2 = SMTP_AUTH_LOGIN_PASSWD; | ||||||
|     smtpc->authused = SASL_MECH_LOGIN; |     smtpc->authused = SASL_MECH_LOGIN; | ||||||
| @@ -509,7 +526,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else if((smtpc->authmechs & SASL_MECH_PLAIN) && |   else if((smtpc->authmechs & SASL_MECH_PLAIN) && | ||||||
|           (smtpc->prefmech & SASL_MECH_PLAIN)) { |           (smtpc->prefmech & SASL_MECH_PLAIN)) { | ||||||
|     mech = "PLAIN"; |     mech = SASL_MECH_STRING_PLAIN; | ||||||
|     state1 = SMTP_AUTH_PLAIN; |     state1 = SMTP_AUTH_PLAIN; | ||||||
|     state2 = SMTP_AUTH_FINAL; |     state2 = SMTP_AUTH_FINAL; | ||||||
|     smtpc->authused = SASL_MECH_PLAIN; |     smtpc->authused = SASL_MECH_PLAIN; | ||||||
| @@ -636,7 +653,7 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct SMTP *smtp = data->state.proto.smtp; |   struct SMTP *smtp = data->req.protop; | ||||||
|  |  | ||||||
|   /* Send the RCPT TO command */ |   /* Send the RCPT TO command */ | ||||||
|   if(smtp->rcpt) { |   if(smtp->rcpt) { | ||||||
| @@ -1088,6 +1105,43 @@ static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn, | |||||||
| } | } | ||||||
| #endif | #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 */ | /* For the final responses to the AUTH sequence */ | ||||||
| static CURLcode smtp_state_auth_final_resp(struct connectdata *conn, | static CURLcode smtp_state_auth_final_resp(struct connectdata *conn, | ||||||
|                                            int smtpcode, |                                            int smtpcode, | ||||||
| @@ -1115,7 +1169,7 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 */ |   (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; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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 */ |   (void)instate; /* no use for this yet */ | ||||||
|  |  | ||||||
| @@ -1296,6 +1350,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) | |||||||
|       break; |       break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     case SMTP_AUTH_XOAUTH2: | ||||||
|  |       result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|     case SMTP_AUTH_FINAL: |     case SMTP_AUTH_FINAL: | ||||||
|       result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state); |       result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state); | ||||||
|       break; |       break; | ||||||
| @@ -1334,11 +1392,13 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) | |||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct smtp_conn *smtpc = &conn->proto.smtpc; |   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); |     result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); | ||||||
|   else |     if(result || !smtpc->ssldone) | ||||||
|     result = Curl_pp_statemach(&smtpc->pp, FALSE); |       return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   result = Curl_pp_statemach(&smtpc->pp, FALSE); | ||||||
|   *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; |   *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| @@ -1361,13 +1421,11 @@ static CURLcode smtp_init(struct connectdata *conn) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct SMTP *smtp = data->state.proto.smtp; |   struct SMTP *smtp; | ||||||
|  |  | ||||||
|   if(!smtp) { |   smtp = data->req.protop = calloc(sizeof(struct SMTP), 1); | ||||||
|     smtp = data->state.proto.smtp = calloc(sizeof(struct SMTP), 1); |  | ||||||
|   if(!smtp) |   if(!smtp) | ||||||
|     result = CURLE_OUT_OF_MEMORY; |     result = CURLE_OUT_OF_MEMORY; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -1397,15 +1455,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to not done yet */ |   *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 */ |   /* We always support persistent connections in SMTP */ | ||||||
|   conn->bits.close = FALSE; |   conn->bits.close = FALSE; | ||||||
|  |  | ||||||
| @@ -1453,7 +1502,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   struct pingpong *pp = &conn->proto.smtpc.pp; | ||||||
|   const char *eob; |   const char *eob; | ||||||
|   ssize_t len; |   ssize_t len; | ||||||
| @@ -1534,7 +1583,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, | |||||||
|  |  | ||||||
|   if(conn->data->set.opt_no_body) { |   if(conn->data->set.opt_no_body) { | ||||||
|     /* Requested no body means no transfer */ |     /* 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; |     smtp->transfer = FTPTRANSFER_INFO; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -1571,15 +1620,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; /* default to false */ |   *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); |   result = smtp_regular_transfer(conn, done); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| @@ -1622,7 +1662,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn, | |||||||
| /* Call this when the DO phase has completed */ | /* Call this when the DO phase has completed */ | ||||||
| static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) | 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; |   (void)connected; | ||||||
|  |  | ||||||
| @@ -1687,6 +1727,7 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn, | |||||||
| static CURLcode smtp_setup_connection(struct connectdata *conn) | static CURLcode smtp_setup_connection(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |   CURLcode result; | ||||||
|  |  | ||||||
|   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { |   if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { | ||||||
|     /* Unless we have asked to tunnel SMTP operations through the proxy, we |     /* 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; |       return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| #endif | #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 | #else | ||||||
|     failf(data, "SMTP over http proxy requires HTTP support built-in!"); |     failf(data, "SMTP over http proxy requires HTTP support built-in!"); | ||||||
|     return CURLE_UNSUPPORTED_PROTOCOL; |     return CURLE_UNSUPPORTED_PROTOCOL; | ||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /* Initialise the SMTP layer */ | ||||||
|  |   result = smtp_init(conn); | ||||||
|  |   if(result) | ||||||
|  |     return result; | ||||||
|  |  | ||||||
|   data->state.path++;   /* don't include the initial slash */ |   data->state.path++;   /* don't include the initial slash */ | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| @@ -1742,18 +1786,20 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn) | |||||||
|  |  | ||||||
|       if(strequal(value, "*")) |       if(strequal(value, "*")) | ||||||
|         smtpc->prefmech = SASL_AUTH_ANY; |         smtpc->prefmech = SASL_AUTH_ANY; | ||||||
|       else if(strequal(value, "LOGIN")) |       else if(strequal(value, SASL_MECH_STRING_LOGIN)) | ||||||
|         smtpc->prefmech = SASL_MECH_LOGIN; |         smtpc->prefmech = SASL_MECH_LOGIN; | ||||||
|       else if(strequal(value, "PLAIN")) |       else if(strequal(value, SASL_MECH_STRING_PLAIN)) | ||||||
|         smtpc->prefmech = SASL_MECH_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; |         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; |         smtpc->prefmech = SASL_MECH_DIGEST_MD5; | ||||||
|       else if(strequal(value, "GSSAPI")) |       else if(strequal(value, SASL_MECH_STRING_GSSAPI)) | ||||||
|         smtpc->prefmech = SASL_MECH_GSSAPI; |         smtpc->prefmech = SASL_MECH_GSSAPI; | ||||||
|       else if(strequal(value, "NTLM")) |       else if(strequal(value, SASL_MECH_STRING_NTLM)) | ||||||
|         smtpc->prefmech = SASL_MECH_NTLM; |         smtpc->prefmech = SASL_MECH_NTLM; | ||||||
|  |       else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) | ||||||
|  |         smtpc->prefmech = SASL_MECH_XOAUTH2; | ||||||
|       else |       else | ||||||
|         smtpc->prefmech = SASL_AUTH_NONE; |         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 i; | ||||||
|   ssize_t si; |   ssize_t si; | ||||||
|   struct SessionHandle *data = conn->data; |   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? */ |   /* Do we need to allocate the scatch buffer? */ | ||||||
|   if(!data->state.scratch) { |   if(!data->state.scratch) { | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ typedef enum { | |||||||
|   SMTP_AUTH_DIGESTMD5_RESP, |   SMTP_AUTH_DIGESTMD5_RESP, | ||||||
|   SMTP_AUTH_NTLM, |   SMTP_AUTH_NTLM, | ||||||
|   SMTP_AUTH_NTLM_TYPE2MSG, |   SMTP_AUTH_NTLM_TYPE2MSG, | ||||||
|  |   SMTP_AUTH_XOAUTH2, | ||||||
|   SMTP_AUTH_FINAL, |   SMTP_AUTH_FINAL, | ||||||
|   SMTP_MAIL,        /* MAIL FROM */ |   SMTP_MAIL,        /* MAIL FROM */ | ||||||
|   SMTP_RCPT,        /* RCPT TO */ |   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 */ |                                                        number of sockets */ | ||||||
|                                int numsocks); |                                int numsocks); | ||||||
|  |  | ||||||
|  | static CURLcode ssh_setup_connection(struct connectdata *conn); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * SCP protocol handler. |  * SCP protocol handler. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_scp = { | const struct Curl_handler Curl_handler_scp = { | ||||||
|   "SCP",                                /* scheme */ |   "SCP",                                /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   ssh_setup_connection,                 /* setup_connection */ | ||||||
|   ssh_do,                               /* do_it */ |   ssh_do,                               /* do_it */ | ||||||
|   scp_done,                             /* done */ |   scp_done,                             /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -181,7 +183,7 @@ const struct Curl_handler Curl_handler_scp = { | |||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_sftp = { | const struct Curl_handler Curl_handler_sftp = { | ||||||
|   "SFTP",                               /* scheme */ |   "SFTP",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   ssh_setup_connection,                 /* setup_connection */ | ||||||
|   ssh_do,                               /* do_it */ |   ssh_do,                               /* do_it */ | ||||||
|   sftp_done,                            /* done */ |   sftp_done,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
| @@ -200,7 +202,6 @@ const struct Curl_handler Curl_handler_sftp = { | |||||||
|   | PROTOPT_NOURLQUERY                  /* flags */ |   | PROTOPT_NOURLQUERY                  /* flags */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| kbd_callback(const char *name, int name_len, const char *instruction, | kbd_callback(const char *name, int name_len, const char *instruction, | ||||||
|              int instruction_len, int num_prompts, |              int instruction_len, int num_prompts, | ||||||
| @@ -687,7 +688,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) | |||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   struct ssh_conn *sshc = &conn->proto.sshc; | ||||||
|   curl_socket_t sock = conn->sock[FIRSTSOCKET]; |   curl_socket_t sock = conn->sock[FIRSTSOCKET]; | ||||||
|   char *new_readdir_line; |   char *new_readdir_line; | ||||||
| @@ -2287,6 +2288,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) | |||||||
|         sshc->actualcode = result; |         sshc->actualcode = result; | ||||||
|       } |       } | ||||||
|       else { |       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 |         /* we want to use the _sending_ function even when the socket turns | ||||||
|            out readable as the underlying libssh2 scp send function will deal |            out readable as the underlying libssh2 scp send function will deal | ||||||
|            with both accordingly */ |            with both accordingly */ | ||||||
| @@ -2603,9 +2608,7 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block) | |||||||
| { | { | ||||||
|   struct ssh_conn *sshc = &conn->proto.sshc; |   struct ssh_conn *sshc = &conn->proto.sshc; | ||||||
|   int dir; |   int dir; | ||||||
|   if(!block) |   if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) { | ||||||
|     conn->waitfor = 0; |  | ||||||
|   else if((dir = libssh2_session_block_directions(sshc->ssh_session))) { |  | ||||||
|     /* translate the libssh2 define bits into our own bit defines */ |     /* translate the libssh2 define bits into our own bit defines */ | ||||||
|     conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | |     conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | | ||||||
|       ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND: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 |  * 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 SSHPROTO *ssh; | ||||||
|   struct ssh_conn *sshc = &conn->proto.sshc; |  | ||||||
|  |  | ||||||
|   sshc->actualcode = CURLE_OK; /* reset error code */ |   conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO)); | ||||||
|   sshc->secondCreateDirs =0;   /* reset the create dir attempt state |  | ||||||
|                                   variable */ |  | ||||||
|  |  | ||||||
|   if(data->state.proto.ssh) |  | ||||||
|     return CURLE_OK; |  | ||||||
|  |  | ||||||
|   ssh = calloc(1, sizeof(struct SSHPROTO)); |  | ||||||
|   if(!ssh) |   if(!ssh) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   data->state.proto.ssh = ssh; |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |   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. */ |      function to make the re-use checks properly be able to check this bit. */ | ||||||
|   conn->bits.close = FALSE; |   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) { |   if(conn->handler->protocol & CURLPROTO_SCP) { | ||||||
|     conn->recv[FIRSTSOCKET] = scp_recv; |     conn->recv[FIRSTSOCKET] = scp_recv; | ||||||
|     conn->send[FIRSTSOCKET] = scp_send; |     conn->send[FIRSTSOCKET] = scp_send; | ||||||
| @@ -2856,23 +2840,16 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done) | |||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   bool connected = 0; |   bool connected = 0; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |   struct ssh_conn *sshc = &conn->proto.sshc; | ||||||
|  |  | ||||||
|   *done = FALSE; /* default to false */ |   *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 */ |   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_pgrsSetUploadCounter(data, 0); | ||||||
|   Curl_pgrsSetDownloadCounter(data, 0); |   Curl_pgrsSetDownloadCounter(data, 0); | ||||||
|   Curl_pgrsSetUploadSize(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; |   struct ssh_conn *ssh = &conn->proto.sshc; | ||||||
|   (void) dead_connection; |   (void) dead_connection; | ||||||
|  |  | ||||||
|   Curl_safefree(conn->data->state.proto.ssh); |   Curl_safefree(conn->data->req.protop); | ||||||
|  |  | ||||||
|   if(ssh->ssh_session) { |   if(ssh->ssh_session) { | ||||||
|     /* only if there's a session still around to use! */ |     /* 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) | static CURLcode ssh_done(struct connectdata *conn, CURLcode status) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   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) { |   if(status == CURLE_OK) { | ||||||
|     /* run the state-machine |     /* 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")); |   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) { |   if(conn->proto.sshc.ssh_session) { | ||||||
|     /* only if there's a session still around to use! */ |     /* 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; |   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 | static | ||||||
| int cert_stuff(struct connectdata *conn, | int cert_stuff(struct connectdata *conn, | ||||||
|                SSL_CTX* ctx, |                SSL_CTX* ctx, | ||||||
| @@ -527,7 +570,16 @@ int cert_stuff(struct connectdata *conn, | |||||||
|         EVP_PKEY *priv_key = NULL; |         EVP_PKEY *priv_key = NULL; | ||||||
|         if(data->state.engine) { |         if(data->state.engine) { | ||||||
| #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS | #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 | #endif | ||||||
|           /* the typecast below was added to please mingw32 */ |           /* the typecast below was added to please mingw32 */ | ||||||
|           priv_key = (EVP_PKEY *) |           priv_key = (EVP_PKEY *) | ||||||
| @@ -536,6 +588,9 @@ int cert_stuff(struct connectdata *conn, | |||||||
|                                     ui_method, |                                     ui_method, | ||||||
| #endif | #endif | ||||||
|                                     data->set.str[STRING_KEY_PASSWD]); |                                     data->set.str[STRING_KEY_PASSWD]); | ||||||
|  | #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS | ||||||
|  |           UI_destroy_method(ui_method); | ||||||
|  | #endif | ||||||
|           if(!priv_key) { |           if(!priv_key) { | ||||||
|             failf(data, "failed to load private key from crypto engine"); |             failf(data, "failed to load private key from crypto engine"); | ||||||
|             return 0; |             return 0; | ||||||
| @@ -1137,6 +1192,8 @@ static CURLcode verifyhost(struct connectdata *conn, | |||||||
|     /* an alternative name field existed, but didn't match and then |     /* an alternative name field existed, but didn't match and then | ||||||
|        we MUST fail */ |        we MUST fail */ | ||||||
|     infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); |     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; |     res = CURLE_PEER_FAILED_VERIFICATION; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| @@ -1755,7 +1812,7 @@ ossl_connect_step2(struct connectdata *conn, int sockindex) | |||||||
|        */ |        */ | ||||||
|       if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) { |       if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) { | ||||||
|         failf(data, "Unknown SSL protocol error in connection to %s:%ld ", |         failf(data, "Unknown SSL protocol error in connection to %s:%ld ", | ||||||
|               conn->host.name, conn->port); |               conn->host.name, conn->remote_port); | ||||||
|         return rc; |         return rc; | ||||||
|       } |       } | ||||||
|       /* Could be a CERT problem */ |       /* Could be a CERT problem */ | ||||||
| @@ -2296,7 +2353,7 @@ ossl_connect_step3(struct connectdata *conn, | |||||||
|    * operations. |    * operations. | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|   if(!data->set.ssl.verifypeer) |   if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost) | ||||||
|     (void)servercert(conn, connssl, FALSE); |     (void)servercert(conn, connssl, FALSE); | ||||||
|   else |   else | ||||||
|     retcode = servercert(conn, connssl, TRUE); |     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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -361,6 +361,9 @@ curl_multi_strerror(CURLMcode error) | |||||||
|   case CURLM_UNKNOWN_OPTION: |   case CURLM_UNKNOWN_OPTION: | ||||||
|     return "Unknown option"; |     return "Unknown option"; | ||||||
|  |  | ||||||
|  |   case CURLM_ADDED_ALREADY: | ||||||
|  |     return "The easy handle is already added to a multi handle"; | ||||||
|  |  | ||||||
|   case CURLM_LAST: |   case CURLM_LAST: | ||||||
|     break; |     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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -247,7 +247,7 @@ CURLcode init_telnet(struct connectdata *conn) | |||||||
|   if(!tn) |   if(!tn) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     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; |   tn->telrcv_state = CURL_TS_DATA; | ||||||
|  |  | ||||||
| @@ -292,7 +292,7 @@ CURLcode init_telnet(struct connectdata *conn) | |||||||
| static void negotiate(struct connectdata *conn) | static void negotiate(struct connectdata *conn) | ||||||
| { | { | ||||||
|   int i; |   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++) { |   for(i = 0;i < CURL_NTELOPTS;i++) { | ||||||
|     if(i==CURL_TELOPT_ECHO) |     if(i==CURL_TELOPT_ECHO) | ||||||
| @@ -366,7 +366,7 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option) | |||||||
| static | static | ||||||
| void set_remote_option(struct connectdata *conn, int option, int newstate) | 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) { |   if(newstate == CURL_YES) { | ||||||
|     switch(tn->him[option]) { |     switch(tn->him[option]) { | ||||||
|     case CURL_NO: |     case CURL_NO: | ||||||
| @@ -440,7 +440,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) | |||||||
| static | static | ||||||
| void rec_will(struct connectdata *conn, int option) | 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]) { |   switch(tn->him[option]) { | ||||||
|   case CURL_NO: |   case CURL_NO: | ||||||
|     if(tn->him_preferred[option] == CURL_YES) { |     if(tn->him_preferred[option] == CURL_YES) { | ||||||
| @@ -488,7 +488,7 @@ void rec_will(struct connectdata *conn, int option) | |||||||
| static | static | ||||||
| void rec_wont(struct connectdata *conn, int option) | 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]) { |   switch(tn->him[option]) { | ||||||
|   case CURL_NO: |   case CURL_NO: | ||||||
|     /* Already disabled */ |     /* Already disabled */ | ||||||
| @@ -530,7 +530,7 @@ void rec_wont(struct connectdata *conn, int option) | |||||||
| static void | static void | ||||||
| set_local_option(struct connectdata *conn, int option, int newstate) | 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) { |   if(newstate == CURL_YES) { | ||||||
|     switch(tn->us[option]) { |     switch(tn->us[option]) { | ||||||
|     case CURL_NO: |     case CURL_NO: | ||||||
| @@ -604,7 +604,7 @@ set_local_option(struct connectdata *conn, int option, int newstate) | |||||||
| static | static | ||||||
| void rec_do(struct connectdata *conn, int option) | 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]) { |   switch(tn->us[option]) { | ||||||
|   case CURL_NO: |   case CURL_NO: | ||||||
|     if(tn->us_preferred[option] == CURL_YES) { |     if(tn->us_preferred[option] == CURL_YES) { | ||||||
| @@ -664,7 +664,7 @@ void rec_do(struct connectdata *conn, int option) | |||||||
| static | static | ||||||
| void rec_dont(struct connectdata *conn, int option) | 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]) { |   switch(tn->us[option]) { | ||||||
|   case CURL_NO: |   case CURL_NO: | ||||||
|     /* Already disabled */ |     /* Already disabled */ | ||||||
| @@ -825,7 +825,7 @@ static CURLcode check_telnet_options(struct connectdata *conn) | |||||||
|   char option_keyword[128]; |   char option_keyword[128]; | ||||||
|   char option_arg[256]; |   char option_arg[256]; | ||||||
|   struct SessionHandle *data = conn->data; |   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; |   CURLcode result = CURLE_OK; | ||||||
|   int binary_option; |   int binary_option; | ||||||
|  |  | ||||||
| @@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn) | |||||||
|   char varname[128]; |   char varname[128]; | ||||||
|   char varval[128]; |   char varval[128]; | ||||||
|   struct SessionHandle *data = conn->data; |   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); |   printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); | ||||||
|   switch (CURL_SB_GET(tn)) { |   switch (CURL_SB_GET(tn)) { | ||||||
| @@ -1009,7 +1009,7 @@ static void sendsuboption(struct connectdata *conn, int option) | |||||||
|   unsigned char*uc1, *uc2; |   unsigned char*uc1, *uc2; | ||||||
|  |  | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct TELNET *tn = (struct TELNET *)data->state.proto.telnet; |   struct TELNET *tn = (struct TELNET *)data->req.protop; | ||||||
|  |  | ||||||
|   switch (option) { |   switch (option) { | ||||||
|   case CURL_TELOPT_NAWS: |   case CURL_TELOPT_NAWS: | ||||||
| @@ -1067,7 +1067,7 @@ CURLcode telrcv(struct connectdata *conn, | |||||||
|   int in = 0; |   int in = 0; | ||||||
|   int startwrite=-1; |   int startwrite=-1; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct TELNET *tn = (struct TELNET *)data->state.proto.telnet; |   struct TELNET *tn = (struct TELNET *)data->req.protop; | ||||||
|  |  | ||||||
| #define startskipping()                                       \ | #define startskipping()                                       \ | ||||||
|   if(startwrite >= 0) {                                       \ |   if(startwrite >= 0) {                                       \ | ||||||
| @@ -1264,7 +1264,7 @@ static CURLcode send_telnet_data(struct connectdata *conn, | |||||||
| static CURLcode telnet_done(struct connectdata *conn, | static CURLcode telnet_done(struct connectdata *conn, | ||||||
|                                  CURLcode status, bool premature) |                                  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)status; /* unused */ | ||||||
|   (void)premature; /* not used */ |   (void)premature; /* not used */ | ||||||
|  |  | ||||||
| @@ -1274,7 +1274,7 @@ static CURLcode telnet_done(struct connectdata *conn, | |||||||
|   curl_slist_free_all(tn->telnet_vars); |   curl_slist_free_all(tn->telnet_vars); | ||||||
|   tn->telnet_vars = NULL; |   tn->telnet_vars = NULL; | ||||||
|  |  | ||||||
|   Curl_safefree(conn->data->state.proto.telnet); |   Curl_safefree(conn->data->req.protop); | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
| @@ -1318,7 +1318,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) | |||||||
|   if(code) |   if(code) | ||||||
|     return code; |     return code; | ||||||
|  |  | ||||||
|   tn = (struct TELNET *)data->state.proto.telnet; |   tn = (struct TELNET *)data->req.protop; | ||||||
|  |  | ||||||
|   code = check_telnet_options(conn); |   code = check_telnet_options(conn); | ||||||
|   if(code) |   if(code) | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								lib/tftp.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								lib/tftp.c
									
									
									
									
									
								
							| @@ -56,6 +56,7 @@ | |||||||
| #include "multiif.h" | #include "multiif.h" | ||||||
| #include "url.h" | #include "url.h" | ||||||
| #include "rawstr.h" | #include "rawstr.h" | ||||||
|  | #include "speedcheck.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -947,10 +948,6 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   blksize = TFTP_BLKSIZE_DEFAULT; |   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)); |   state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); | ||||||
|   if(!state) |   if(!state) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
| @@ -1259,6 +1256,15 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) | |||||||
|   if(*dophase_done) { |   if(*dophase_done) { | ||||||
|     DEBUGF(infof(conn->data, "DO phase is complete\n")); |     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; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1307,14 +1313,6 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = FALSE; |   *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) { |   if(!conn->proto.tftpc) { | ||||||
|     code = tftp_connect(conn, done); |     code = tftp_connect(conn, done); | ||||||
|     if(code) |     if(code) | ||||||
|   | |||||||
| @@ -101,8 +101,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) | |||||||
| #ifdef CURL_DOES_CONVERSIONS | #ifdef CURL_DOES_CONVERSIONS | ||||||
|   bool sending_http_headers = FALSE; |   bool sending_http_headers = FALSE; | ||||||
|  |  | ||||||
|   if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) && |   if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { | ||||||
|      (data->state.proto.http->sending == HTTPSEND_REQUEST)) { |     const struct HTTP *http = data->req.protop; | ||||||
|  |  | ||||||
|  |     if(http->sending == HTTPSEND_REQUEST) | ||||||
|       /* We're sending the HTTP request headers, not the data. |       /* We're sending the HTTP request headers, not the data. | ||||||
|          Remember that so we don't re-translate them into garbage. */ |          Remember that so we don't re-translate them into garbage. */ | ||||||
|       sending_http_headers = TRUE; |       sending_http_headers = TRUE; | ||||||
| @@ -540,6 +542,10 @@ static CURLcode readwrite_data(struct SessionHandle *data, | |||||||
|  |  | ||||||
|             if(!Curl_meets_timecondition(data, k->timeofdoc)) { |             if(!Curl_meets_timecondition(data, k->timeofdoc)) { | ||||||
|               *done = TRUE; |               *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 |               /* we abort the transfer before it is completed == we ruin the | ||||||
|                  re-use ability. Close the connection */ |                  re-use ability. Close the connection */ | ||||||
|               conn->bits.close = TRUE; |               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 |         /* HTTP pollution, this should be written nicer to become more | ||||||
|            protocol agnostic. */ |            protocol agnostic. */ | ||||||
|         int fillcount; |         int fillcount; | ||||||
|  |         struct HTTP *http = data->req.protop; | ||||||
|  |  | ||||||
|         if((k->exp100 == EXP100_SENDING_REQUEST) && |         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: |           /* 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 |              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 */ |              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(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. |             /* We're sending the HTTP request headers, not the data. | ||||||
|                Remember that so we don't change the line endings. */ |                Remember that so we don't change the line endings. */ | ||||||
|             sending_http_headers = TRUE; |             sending_http_headers = TRUE; | ||||||
| @@ -1870,10 +1877,12 @@ CURLcode Curl_retry_request(struct connectdata *conn, | |||||||
|                                 transferred! */ |                                 transferred! */ | ||||||
|  |  | ||||||
|  |  | ||||||
|     if((conn->handler->protocol&CURLPROTO_HTTP) && |     if(conn->handler->protocol&CURLPROTO_HTTP) { | ||||||
|        data->state.proto.http->writebytecount) |       struct HTTP *http = data->req.protop; | ||||||
|  |       if(http->writebytecount) | ||||||
|         return Curl_readrewind(conn); |         return Curl_readrewind(conn); | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1930,6 +1939,7 @@ Curl_setup_transfer( | |||||||
|       k->keepon |= KEEP_RECV; |       k->keepon |= KEEP_RECV; | ||||||
|  |  | ||||||
|     if(conn->writesockfd != CURL_SOCKET_BAD) { |     if(conn->writesockfd != CURL_SOCKET_BAD) { | ||||||
|  |       struct HTTP *http = data->req.protop; | ||||||
|       /* HTTP 1.1 magic: |       /* HTTP 1.1 magic: | ||||||
|  |  | ||||||
|          Even if we require a 100-return code before uploading data, we might |          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 |          state info where we wait for the 100-return code | ||||||
|       */ |       */ | ||||||
|       if((data->state.expect100header) && |       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 */ |         /* wait with write until we either got 100-continue or a timeout */ | ||||||
|         k->exp100 = EXP100_AWAITING_CONTINUE; |         k->exp100 = EXP100_AWAITING_CONTINUE; | ||||||
|         k->start100 = Curl_tvnow(); |         k->start100 = Curl_tvnow(); | ||||||
|  |  | ||||||
|         /* set a timeout for the multi interface */ |         /* Set a timeout for the multi interface. Add the inaccuracy margin so | ||||||
|         Curl_expire(data, CURL_TIMEOUT_EXPECT_100); |            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 { |       else { | ||||||
|         if(data->state.expect100header) |         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 do_init(struct connectdata *conn); | ||||||
| static CURLcode parse_url_login(struct SessionHandle *data, | static CURLcode parse_url_login(struct SessionHandle *data, | ||||||
|                                 struct connectdata *conn, |                                 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, | static CURLcode parse_login_details(const char *login, const size_t len, | ||||||
|                                     char **userptr, char **passwdptr, |                                     char **userptr, char **passwdptr, | ||||||
|                                     char **optionsptr); |                                     char **optionsptr); | ||||||
| @@ -417,7 +418,8 @@ CURLcode Curl_close(struct SessionHandle *data) | |||||||
|   Curl_safefree(data->state.pathbuffer); |   Curl_safefree(data->state.pathbuffer); | ||||||
|   data->state.path = NULL; |   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 */ |   /* Close down all open SSL info and sessions */ | ||||||
|   Curl_ssl_close_all(data); |   Curl_ssl_close_all(data); | ||||||
| @@ -611,7 +613,6 @@ CURLcode Curl_open(struct SessionHandle **curl) | |||||||
|     res = CURLE_OUT_OF_MEMORY; |     res = CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     Curl_easy_initHandleData(data); |  | ||||||
|     res = Curl_init_userdefined(&data->set); |     res = Curl_init_userdefined(&data->set); | ||||||
|  |  | ||||||
|     data->state.headersize=HEADERSIZE; |     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 |      * This sets a requested HTTP version to be used. The value is one of | ||||||
|      * the listed enums in curl/curl.h. |      * 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; |     break; | ||||||
|  |  | ||||||
|   case CURLOPT_HTTPAUTH: |   case CURLOPT_HTTPAUTH: | ||||||
| @@ -1568,6 +1574,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, | |||||||
|     result = setstropt(&data->set.str[STRING_PASSWORD], |     result = setstropt(&data->set.str[STRING_PASSWORD], | ||||||
|                        va_arg(param, char *)); |                        va_arg(param, char *)); | ||||||
|     break; |     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: |   case CURLOPT_POSTQUOTE: | ||||||
|     /* |     /* | ||||||
|      * List of RAW FTP commands to use after a transfer |      * 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: |   case CURLOPT_DNS_SERVERS: | ||||||
|     result = Curl_set_dns_servers(data, va_arg(param, char *)); |     result = Curl_set_dns_servers(data, va_arg(param, char *)); | ||||||
|     break; |     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: |   case CURLOPT_TCP_KEEPALIVE: | ||||||
|     data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE; |     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->user); | ||||||
|   Curl_safefree(conn->passwd); |   Curl_safefree(conn->passwd); | ||||||
|  |   Curl_safefree(conn->xoauth2_bearer); | ||||||
|   Curl_safefree(conn->options); |   Curl_safefree(conn->options); | ||||||
|   Curl_safefree(conn->proxyuser); |   Curl_safefree(conn->proxyuser); | ||||||
|   Curl_safefree(conn->proxypasswd); |   Curl_safefree(conn->proxypasswd); | ||||||
| @@ -3606,7 +3629,7 @@ static struct connectdata *allocate_conn(struct SessionHandle *data) | |||||||
|   if(!conn->send_pipe || !conn->recv_pipe) |   if(!conn->send_pipe || !conn->recv_pipe) | ||||||
|     goto error; |     goto error; | ||||||
|  |  | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
|   conn->data_prot = PROT_CLEAR; |   conn->data_prot = PROT_CLEAR; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -3687,7 +3710,8 @@ static CURLcode findprotocol(struct SessionHandle *data, | |||||||
| static CURLcode parseurlandfillconn(struct SessionHandle *data, | static CURLcode parseurlandfillconn(struct SessionHandle *data, | ||||||
|                                     struct connectdata *conn, |                                     struct connectdata *conn, | ||||||
|                                     bool *prot_missing, |                                     bool *prot_missing, | ||||||
|                                     char *user, char *passwd, char *options) |                                     char **userp, char **passwdp, | ||||||
|  |                                     char **optionsp) | ||||||
| { | { | ||||||
|   char *at; |   char *at; | ||||||
|   char *fragment; |   char *fragment; | ||||||
| @@ -3931,7 +3955,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, | |||||||
|    * Parse the login details from the URL and strip them out of |    * Parse the login details from the URL and strip them out of | ||||||
|    * the host name |    * 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) |   if(result != CURLE_OK) | ||||||
|     return result; |     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. |  * This MUST get called after proxy magic has been figured out. | ||||||
| ***************************************************************/ |  */ | ||||||
| static CURLcode setup_connection_internals(struct connectdata *conn) | static CURLcode setup_connection_internals(struct connectdata *conn) | ||||||
| { | { | ||||||
|   const struct Curl_handler * p; |   const struct Curl_handler * p; | ||||||
|   CURLcode result; |   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. */ |   /* Perform setup complement if some. */ | ||||||
|   p = conn->handler; |   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 |     /* we check for -1 here since if proxy was detected already, this | ||||||
|        was very likely already set to the proxy port */ |        was very likely already set to the proxy port */ | ||||||
|     conn->port = p->defport; |     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; |     conn->remote_port = (unsigned short)conn->given->defport; | ||||||
|  |  | ||||||
|   return CURLE_OK; |   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 | #ifndef CURL_DISABLE_PROXY | ||||||
| /**************************************************************** | /**************************************************************** | ||||||
| * Checks if the host is in the noproxy list. returns true if it matches | * 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, | static CURLcode parse_url_login(struct SessionHandle *data, | ||||||
|                                 struct connectdata *conn, |                                 struct connectdata *conn, | ||||||
|                                 char *user, char *passwd, char *options) |                                 char **user, char **passwd, char **options) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   char *userp = NULL; |   char *userp = NULL; | ||||||
| @@ -4428,16 +4480,16 @@ static CURLcode parse_url_login(struct SessionHandle *data, | |||||||
|   char *ptr = strchr(conn->host.name, '@'); |   char *ptr = strchr(conn->host.name, '@'); | ||||||
|   char *login = conn->host.name; |   char *login = conn->host.name; | ||||||
|  |  | ||||||
|   user[0] = 0;   /* to make everything well-defined */ |   DEBUGASSERT(!**user); | ||||||
|   passwd[0] = 0; |   DEBUGASSERT(!**passwd); | ||||||
|   options[0] = 0; |   DEBUGASSERT(!**options); | ||||||
|  |  | ||||||
|  |   if(!ptr) | ||||||
|  |     goto out; | ||||||
|  |  | ||||||
|   /* We will now try to extract the |   /* We will now try to extract the | ||||||
|    * possible login information in a string like: |    * possible login information in a string like: | ||||||
|    * ftp://user:password@ftp.my.site:8021/README */ |    * ftp://user:password@ftp.my.site:8021/README */ | ||||||
|   if(ptr) { |  | ||||||
|     /* There's login information to the left of the @ */ |  | ||||||
|  |  | ||||||
|   conn->host.name = ++ptr; |   conn->host.name = ++ptr; | ||||||
|  |  | ||||||
|   /* So the hostname is sane.  Only bother interpreting the |   /* 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 :-( |    * 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 */ |   /* We could use the login information in the URL so extract it */ | ||||||
|   result = parse_login_details(login, ptr - login - 1, |   result = parse_login_details(login, ptr - login - 1, | ||||||
|                                &userp, &passwdp, &optionsp); |                                &userp, &passwdp, &optionsp); | ||||||
|       if(!result) { |   if(result != CURLE_OK) | ||||||
|  |     goto out; | ||||||
|  |  | ||||||
|   if(userp) { |   if(userp) { | ||||||
|     char *newname; |     char *newname; | ||||||
|  |  | ||||||
| @@ -4461,56 +4517,44 @@ static CURLcode parse_url_login(struct SessionHandle *data, | |||||||
|     /* Decode the user */ |     /* Decode the user */ | ||||||
|     newname = curl_easy_unescape(data, userp, 0, NULL); |     newname = curl_easy_unescape(data, userp, 0, NULL); | ||||||
|     if(!newname) { |     if(!newname) { | ||||||
|             Curl_safefree(userp); |       result = CURLE_OUT_OF_MEMORY; | ||||||
|             Curl_safefree(passwdp); |       goto out; | ||||||
|             Curl_safefree(optionsp); |  | ||||||
|             return CURLE_OUT_OF_MEMORY; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|           if(strlen(newname) < MAX_CURL_USER_LENGTH) |     free(*user); | ||||||
|             strcpy(user, newname); |     *user = newname; | ||||||
|  |  | ||||||
|           free(newname); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(passwdp) { |   if(passwdp) { | ||||||
|     /* We have a password in the URL so decode it */ |     /* We have a password in the URL so decode it */ | ||||||
|     char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); |     char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); | ||||||
|     if(!newpasswd) { |     if(!newpasswd) { | ||||||
|             Curl_safefree(userp); |       result = CURLE_OUT_OF_MEMORY; | ||||||
|             Curl_safefree(passwdp); |       goto out; | ||||||
|             Curl_safefree(optionsp); |  | ||||||
|             return CURLE_OUT_OF_MEMORY; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|           if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) |     free(*passwd); | ||||||
|             strcpy(passwd, newpasswd); |     *passwd = newpasswd; | ||||||
|  |  | ||||||
|           free(newpasswd); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(optionsp) { |   if(optionsp) { | ||||||
|     /* We have an options list in the URL so decode it */ |     /* We have an options list in the URL so decode it */ | ||||||
|     char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); |     char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); | ||||||
|     if(!newoptions) { |     if(!newoptions) { | ||||||
|             Curl_safefree(userp); |       result = CURLE_OUT_OF_MEMORY; | ||||||
|             Curl_safefree(passwdp); |       goto out; | ||||||
|             Curl_safefree(optionsp); |  | ||||||
|             return CURLE_OUT_OF_MEMORY; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|           if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) |     free(*options); | ||||||
|             strcpy(options, newoptions); |     *options = newoptions; | ||||||
|  |   } | ||||||
|  |  | ||||||
|           free(newoptions); |  | ||||||
|         } |   out: | ||||||
|       } |  | ||||||
|  |  | ||||||
|   Curl_safefree(userp); |   Curl_safefree(userp); | ||||||
|   Curl_safefree(passwdp); |   Curl_safefree(passwdp); | ||||||
|   Curl_safefree(optionsp); |   Curl_safefree(optionsp); | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result; |   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 |  * Override the login details from the URL with that in the CURLOPT_USERPWD | ||||||
|  * option or a .netrc file, if applicable. |  * option or a .netrc file, if applicable. | ||||||
|  */ |  */ | ||||||
| static void override_login(struct SessionHandle *data, | static CURLcode override_login(struct SessionHandle *data, | ||||||
|                                struct connectdata *conn, |                                struct connectdata *conn, | ||||||
|                            char *user, char *passwd, char *options) |                                char **userp, char **passwdp, char **optionsp) | ||||||
| { | { | ||||||
|   if(data->set.str[STRING_USERNAME]) { |   if(data->set.str[STRING_USERNAME]) { | ||||||
|     strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); |     free(*userp); | ||||||
|     user[MAX_CURL_USER_LENGTH - 1] = '\0';   /* To be on safe side */ |     *userp = strdup(data->set.str[STRING_USERNAME]); | ||||||
|  |     if(!*userp) | ||||||
|  |       return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(data->set.str[STRING_PASSWORD]) { |   if(data->set.str[STRING_PASSWORD]) { | ||||||
|     strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); |     free(*passwdp); | ||||||
|     passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ |     *passwdp = strdup(data->set.str[STRING_PASSWORD]); | ||||||
|  |     if(!*passwdp) | ||||||
|  |       return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(data->set.str[STRING_OPTIONS]) { |   if(data->set.str[STRING_OPTIONS]) { | ||||||
|     strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); |     free(*optionsp); | ||||||
|     options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ |     *optionsp = strdup(data->set.str[STRING_OPTIONS]); | ||||||
|  |     if(!*optionsp) | ||||||
|  |       return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   conn->bits.netrc = FALSE; |   conn->bits.netrc = FALSE; | ||||||
|   if(data->set.use_netrc != CURL_NETRC_IGNORED) { |   if(data->set.use_netrc != CURL_NETRC_IGNORED) { | ||||||
|     if(Curl_parsenetrc(conn->host.name, |     if(Curl_parsenetrc(conn->host.name, | ||||||
|                        user, passwd, |                        userp, passwdp, | ||||||
|                        data->set.str[STRING_NETRC_FILE])) { |                        data->set.str[STRING_NETRC_FILE])) { | ||||||
|       infof(data, "Couldn't find host %s in the " |       infof(data, "Couldn't find host %s in the " | ||||||
|             DOT_CHAR "netrc file; using defaults\n", |             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 */ |       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; | ||||||
|   struct connectdata *conn_temp = NULL; |   struct connectdata *conn_temp = NULL; | ||||||
|   size_t urllen; |   size_t urllen; | ||||||
|   char user[MAX_CURL_USER_LENGTH]; |   char *user = NULL; | ||||||
|   char passwd[MAX_CURL_PASSWORD_LENGTH]; |   char *passwd = NULL; | ||||||
|   char options[MAX_CURL_OPTIONS_LENGTH]; |   char *options = NULL; | ||||||
|   bool reuse; |   bool reuse; | ||||||
|   char *proxy = NULL; |   char *proxy = NULL; | ||||||
|   bool prot_missing = FALSE; |   bool prot_missing = FALSE; | ||||||
| @@ -5035,8 +5087,10 @@ static CURLcode create_conn(struct SessionHandle *data, | |||||||
|    * Check input data |    * Check input data | ||||||
|    *************************************************************/ |    *************************************************************/ | ||||||
|  |  | ||||||
|   if(!data->change.url) |   if(!data->change.url) { | ||||||
|     return CURLE_URL_MALFORMAT; |     result = CURLE_URL_MALFORMAT; | ||||||
|  |     goto out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* First, split up the current URL in parts so that we can use the |   /* First, split up the current URL in parts so that we can use the | ||||||
|      parts for checking against the already present connections. In order |      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. */ |      connection data struct and fill in for comparison purposes. */ | ||||||
|   conn = allocate_conn(data); |   conn = allocate_conn(data); | ||||||
|  |  | ||||||
|   if(!conn) |   if(!conn) { | ||||||
|     return CURLE_OUT_OF_MEMORY; |     result = CURLE_OUT_OF_MEMORY; | ||||||
|  |     goto out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* We must set the return variable as soon as possible, so that our |   /* We must set the return variable as soon as possible, so that our | ||||||
|      parent can cleanup any possible allocs we may have done before |      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.path = NULL; | ||||||
|  |  | ||||||
|   data->state.pathbuffer = malloc(urllen+2); |   data->state.pathbuffer = malloc(urllen+2); | ||||||
|   if(NULL == data->state.pathbuffer) |   if(NULL == data->state.pathbuffer) { | ||||||
|     return CURLE_OUT_OF_MEMORY; /* really bad error */ |     result = CURLE_OUT_OF_MEMORY; /* really bad error */ | ||||||
|  |     goto out; | ||||||
|  |   } | ||||||
|   data->state.path = data->state.pathbuffer; |   data->state.path = data->state.pathbuffer; | ||||||
|  |  | ||||||
|   conn->host.rawalloc = malloc(urllen+2); |   conn->host.rawalloc = malloc(urllen+2); | ||||||
|   if(NULL == conn->host.rawalloc) { |   if(NULL == conn->host.rawalloc) { | ||||||
|     Curl_safefree(data->state.pathbuffer); |     Curl_safefree(data->state.pathbuffer); | ||||||
|     data->state.path = NULL; |     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 = conn->host.rawalloc; | ||||||
|   conn->host.name[0] = 0; |   conn->host.name[0] = 0; | ||||||
|  |  | ||||||
|   result = parseurlandfillconn(data, conn, &prot_missing, user, passwd, |   user = strdup(""); | ||||||
|                                options); |   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) |   if(result != CURLE_OK) | ||||||
|     return result; |     goto out; | ||||||
|  |  | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
|    * No protocol part in URL was used, add it! |    * 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); |     reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url); | ||||||
|  |  | ||||||
|     if(!reurl) { |     if(!reurl) { | ||||||
|       Curl_safefree(proxy); |       result = CURLE_OUT_OF_MEMORY; | ||||||
|       return CURLE_OUT_OF_MEMORY; |       goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(data->change.url_alloc) { |     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 | #ifndef CURL_DISABLE_PROXY | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
|    * Extract the user and password from the authentication string |    * 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) { |   if(conn->bits.proxy_user_passwd) { | ||||||
|     result = parse_proxy_auth(data, conn); |     result = parse_proxy_auth(data, conn); | ||||||
|     if(result != CURLE_OK) |     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 global proxy is set, this is it */ | ||||||
|     if(NULL == proxy) { |     if(NULL == proxy) { | ||||||
|       failf(data, "memory shortage"); |       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) { |   if(proxy) { | ||||||
|     result = parse_proxy(data, conn, 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) |     if(result) | ||||||
|       return result; |       goto out; | ||||||
|  |  | ||||||
|     if((conn->proxytype == CURLPROXY_HTTP) || |     if((conn->proxytype == CURLPROXY_HTTP) || | ||||||
|        (conn->proxytype == CURLPROXY_HTTP_1_0)) { |        (conn->proxytype == CURLPROXY_HTTP_1_0)) { | ||||||
| #ifdef CURL_DISABLE_HTTP | #ifdef CURL_DISABLE_HTTP | ||||||
|       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ |       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ | ||||||
|       return CURLE_UNSUPPORTED_PROTOCOL; |       result = CURLE_UNSUPPORTED_PROTOCOL; | ||||||
|  |       goto out; | ||||||
| #else | #else | ||||||
|       /* force this connection's protocol to become HTTP if not already |       /* force this connection's protocol to become HTTP if not already | ||||||
|          compatible - if it isn't tunneling through */ |          compatible - if it isn't tunneling through */ | ||||||
| @@ -5217,15 +5293,36 @@ static CURLcode create_conn(struct SessionHandle *data, | |||||||
|  |  | ||||||
| #endif /* CURL_DISABLE_PROXY */ | #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 |    * Setup internals depending on protocol. Needs to be done after | ||||||
|    * we figured out what/if proxy to use. |    * we figured out what/if proxy to use. | ||||||
|    *************************************************************/ |    *************************************************************/ | ||||||
|   result = setup_connection_internals(conn); |   result = setup_connection_internals(conn); | ||||||
|   if(result != CURLE_OK) { |   if(result != CURLE_OK) | ||||||
|     Curl_safefree(proxy); |     goto out; | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   conn->recv[FIRSTSOCKET] = Curl_recv_plain; |   conn->recv[FIRSTSOCKET] = Curl_recv_plain; | ||||||
|   conn->send[FIRSTSOCKET] = Curl_send_plain; |   conn->send[FIRSTSOCKET] = Curl_send_plain; | ||||||
| @@ -5258,7 +5355,7 @@ static CURLcode create_conn(struct SessionHandle *data, | |||||||
|         DEBUGASSERT(conn->handler->done); |         DEBUGASSERT(conn->handler->done); | ||||||
|         /* we ignore the return code for the protocol-specific DONE */ |         /* we ignore the return code for the protocol-specific DONE */ | ||||||
|         (void)conn->handler->done(conn, result, FALSE); |         (void)conn->handler->done(conn, result, FALSE); | ||||||
|         return result; |         goto out; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ |       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() */ |     /* since we skip do_init() */ | ||||||
|     Curl_speedinit(data); |     do_init(conn); | ||||||
|  |  | ||||||
|     return result; |     goto out; | ||||||
|   } |   } | ||||||
| #endif | #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 |   /* Get a cloned copy of the SSL config situation stored in the | ||||||
|      connection struct. But to get this going nicely, we must first make |      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 |      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]; |   data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) |   if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) { | ||||||
|     return CURLE_OUT_OF_MEMORY; |     result = CURLE_OUT_OF_MEMORY; | ||||||
|  |     goto out; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
|    * Check the current list of connections to see if we can |    * 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); |       conn_free(conn); | ||||||
|       *in_connect = NULL; |       *in_connect = NULL; | ||||||
|  |  | ||||||
|       return CURLE_NO_CONNECTION_AVAILABLE; |       result = CURLE_NO_CONNECTION_AVAILABLE; | ||||||
|  |       goto out; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       /* |       /* | ||||||
| @@ -5439,7 +5519,7 @@ static CURLcode create_conn(struct SessionHandle *data, | |||||||
|    */ |    */ | ||||||
|   result = setup_range(data); |   result = setup_range(data); | ||||||
|   if(result) |   if(result) | ||||||
|     return result; |     goto out; | ||||||
|  |  | ||||||
|   /* Continue connectdata initialization here. */ |   /* Continue connectdata initialization here. */ | ||||||
|  |  | ||||||
| @@ -5457,6 +5537,12 @@ static CURLcode create_conn(struct SessionHandle *data, | |||||||
|    *************************************************************/ |    *************************************************************/ | ||||||
|   result = resolve_server(data, conn, async); |   result = resolve_server(data, conn, async); | ||||||
|  |  | ||||||
|  |   out: | ||||||
|  |  | ||||||
|  |   Curl_safefree(options); | ||||||
|  |   Curl_safefree(passwd); | ||||||
|  |   Curl_safefree(user); | ||||||
|  |   Curl_safefree(proxy); | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -5666,12 +5752,18 @@ CURLcode Curl_done(struct connectdata **connp, | |||||||
|     conn->dns_entry = NULL; |     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 |     /* 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 |        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 |        many callbacks and protocols work differently, we could potentially do | ||||||
|        this more fine-grained in the future. */ |        this more fine-grained in the future. */ | ||||||
|     premature = TRUE; |     premature = TRUE; | ||||||
|  |   default: | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* this calls the protocol-specific function pointer previously set */ |   /* this calls the protocol-specific function pointer previously set */ | ||||||
|   if(conn->handler->done) |   if(conn->handler->done) | ||||||
| @@ -5728,6 +5820,7 @@ CURLcode Curl_done(struct connectdata **connp, | |||||||
|                     this was either closed or handed over to the connection |                     this was either closed or handed over to the connection | ||||||
|                     cache here, and therefore cannot be used from this point on |                     cache here, and therefore cannot be used from this point on | ||||||
|                  */ |                  */ | ||||||
|  |   Curl_free_request_state(data); | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| @@ -5760,9 +5853,6 @@ static CURLcode do_init(struct connectdata *conn) | |||||||
|        HTTP. */ |        HTTP. */ | ||||||
|     data->set.httpreq = HTTPREQ_GET; |     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->start = Curl_tvnow(); /* start time */ | ||||||
|   k->now = k->start;   /* current time is now */ |   k->now = k->start;   /* current time is now */ | ||||||
|   k->header = TRUE; /* assume header */ |   k->header = TRUE; /* assume header */ | ||||||
| @@ -5861,13 +5951,3 @@ CURLcode Curl_do_more(struct connectdata *conn, int *complete) | |||||||
|   return result; |   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_protocol_doing(struct connectdata *conn, bool *done); | ||||||
| CURLcode Curl_setup_conn(struct connectdata *conn, | CURLcode Curl_setup_conn(struct connectdata *conn, | ||||||
|                          bool *protocol_done); |                          bool *protocol_done); | ||||||
|  | void Curl_free_request_state(struct SessionHandle *data); | ||||||
|  |  | ||||||
| int Curl_protocol_getsock(struct connectdata *conn, | int Curl_protocol_getsock(struct connectdata *conn, | ||||||
|                           curl_socket_t *socks, |                           curl_socket_t *socks, | ||||||
| @@ -65,11 +66,6 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data, | |||||||
|  |  | ||||||
| void Curl_close_connections(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_PROXY_PORT 1080 /* default proxy port unless specified */ | ||||||
| #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi | #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi | ||||||
|                                                      service */ |                                                      service */ | ||||||
|   | |||||||
| @@ -222,9 +222,9 @@ | |||||||
| #define CURLMIN(x,y) ((x)<(y)?(x):(y)) | #define CURLMIN(x,y) ((x)<(y)?(x):(y)) | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) | #ifdef HAVE_GSSAPI | ||||||
| /* Types needed for krb4/5-ftp connections */ | /* Types needed for krb5-ftp connections */ | ||||||
| struct krb4buffer { | struct krb5buffer { | ||||||
|   void *data; |   void *data; | ||||||
|   size_t size; |   size_t size; | ||||||
|   size_t index; |   size_t index; | ||||||
| @@ -692,6 +692,9 @@ struct SingleRequest { | |||||||
|   bool forbidchunk;   /* used only to explicitly forbid chunk-upload for |   bool forbidchunk;   /* used only to explicitly forbid chunk-upload for | ||||||
|                          specific upload buffers. See readmoredata() in |                          specific upload buffers. See readmoredata() in | ||||||
|                          http.c for details. */ |                          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 *passwd;  /* password string, allocated */ | ||||||
|   char *options; /* options string, allocated */ |   char *options; /* options string, allocated */ | ||||||
|  |  | ||||||
|  |   char *xoauth2_bearer; /* bearer token for xoauth2, allocated */ | ||||||
|  |  | ||||||
|   char *proxyuser;    /* proxy user name string, allocated */ |   char *proxyuser;    /* proxy user name string, allocated */ | ||||||
|   char *proxypasswd;  /* proxy password string, allocated */ |   char *proxypasswd;  /* proxy password string, allocated */ | ||||||
|   curl_proxytype proxytype; /* what kind of proxy that is in use */ |   curl_proxytype proxytype; /* what kind of proxy that is in use */ | ||||||
| @@ -931,12 +936,12 @@ struct connectdata { | |||||||
|   } allocptr; |   } allocptr; | ||||||
|  |  | ||||||
|   int sec_complete; /* if kerberos is enabled for this connection */ |   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 command_prot; | ||||||
|   enum protection_level data_prot; |   enum protection_level data_prot; | ||||||
|   enum protection_level request_data_prot; |   enum protection_level request_data_prot; | ||||||
|   size_t buffer_size; |   size_t buffer_size; | ||||||
|   struct krb4buffer in_buffer; |   struct krb5buffer in_buffer; | ||||||
|   void *app_data; |   void *app_data; | ||||||
|   const struct Curl_sec_client_mech *mech; |   const struct Curl_sec_client_mech *mech; | ||||||
|   struct sockaddr_in local_addr; |   struct sockaddr_in local_addr; | ||||||
| @@ -996,13 +1001,14 @@ struct connectdata { | |||||||
|  |  | ||||||
|   union { |   union { | ||||||
|     struct ftp_conn ftpc; |     struct ftp_conn ftpc; | ||||||
|  |     struct http_conn httpc; | ||||||
|     struct ssh_conn sshc; |     struct ssh_conn sshc; | ||||||
|     struct tftp_state_data *tftpc; |     struct tftp_state_data *tftpc; | ||||||
|     struct imap_conn imapc; |     struct imap_conn imapc; | ||||||
|     struct pop3_conn pop3c; |     struct pop3_conn pop3c; | ||||||
|     struct smtp_conn smtpc; |     struct smtp_conn smtpc; | ||||||
|     struct rtsp_conn rtspc; |     struct rtsp_conn rtspc; | ||||||
|     void *generic; |     void *generic; /* RTMP and LDAP use this */ | ||||||
|   } proto; |   } proto; | ||||||
|  |  | ||||||
|   int cselect_bits; /* bitmask of socket events */ |   int cselect_bits; /* bitmask of socket events */ | ||||||
| @@ -1149,7 +1155,6 @@ typedef enum { | |||||||
|  * Session-data MUST be put in the connectdata struct and here.  */ |  * Session-data MUST be put in the connectdata struct and here.  */ | ||||||
| #define MAX_CURL_USER_LENGTH 256 | #define MAX_CURL_USER_LENGTH 256 | ||||||
| #define MAX_CURL_PASSWORD_LENGTH 256 | #define MAX_CURL_PASSWORD_LENGTH 256 | ||||||
| #define MAX_CURL_OPTIONS_LENGTH 256 |  | ||||||
|  |  | ||||||
| struct auth { | struct auth { | ||||||
|   unsigned long want;  /* Bitmask set to the authentication methods wanted by |   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_next_server_CSeq; /* the session's next server CSeq */ | ||||||
|   long rtsp_CSeq_recv; /* most recent CSeq received */ |   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) */ |   /* if true, force SSL connection retry (workaround for certain servers) */ | ||||||
|   bool ssl_connect_retry; |   bool ssl_connect_retry; | ||||||
| }; | }; | ||||||
| @@ -1387,6 +1370,8 @@ enum dupstring { | |||||||
|   STRING_TLSAUTH_PASSWORD,     /* TLS auth <password> */ |   STRING_TLSAUTH_PASSWORD,     /* TLS auth <password> */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |   STRING_BEARER,          /* <bearer>, if used */ | ||||||
|  |  | ||||||
|   /* -- end of strings -- */ |   /* -- end of strings -- */ | ||||||
|   STRING_LAST /* not used, just an end-of-list marker */ |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -25,6 +25,7 @@ | |||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include "sslgen.h" | #include "sslgen.h" | ||||||
|  | #include "http2.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use the internal *printf() functions */ | #define _MPRINTF_REPLACE /* use the internal *printf() functions */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -122,6 +123,11 @@ char *curl_version(void) | |||||||
|   left -= len; |   left -= len; | ||||||
|   ptr += len; |   ptr += len; | ||||||
| #endif | #endif | ||||||
|  | #ifdef USE_NGHTTP2 | ||||||
|  |   len = Curl_http2_ver(ptr, left); | ||||||
|  |   left -= len; | ||||||
|  |   ptr += len; | ||||||
|  | #endif | ||||||
| #ifdef USE_LIBRTMP | #ifdef USE_LIBRTMP | ||||||
|   { |   { | ||||||
|     char suff[2]; |     char suff[2]; | ||||||
| @@ -235,9 +241,6 @@ static curl_version_info_data version_info = { | |||||||
| #ifdef ENABLE_IPV6 | #ifdef ENABLE_IPV6 | ||||||
|   | CURL_VERSION_IPV6 |   | CURL_VERSION_IPV6 | ||||||
| #endif | #endif | ||||||
| #ifdef HAVE_KRB4 |  | ||||||
|   | CURL_VERSION_KERBEROS4 |  | ||||||
| #endif |  | ||||||
| #ifdef USE_SSL | #ifdef USE_SSL | ||||||
|   | CURL_VERSION_SSL |   | CURL_VERSION_SSL | ||||||
| #endif | #endif | ||||||
| @@ -277,6 +280,9 @@ static curl_version_info_data version_info = { | |||||||
| #endif | #endif | ||||||
| #if defined(USE_TLS_SRP) | #if defined(USE_TLS_SRP) | ||||||
|   | CURL_VERSION_TLSAUTH_SRP |   | CURL_VERSION_TLSAUTH_SRP | ||||||
|  | #endif | ||||||
|  | #if defined(USE_NGHTTP2) | ||||||
|  |   | CURL_VERSION_HTTP2 | ||||||
| #endif | #endif | ||||||
|   , |   , | ||||||
|   NULL, /* ssl_version */ |   NULL, /* ssl_version */ | ||||||
|   | |||||||
| @@ -1479,7 +1479,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_PROTOTYPE_MISMATCH], [ | |||||||
|           return n; |           return n; | ||||||
|       } |       } | ||||||
|     ]],[[ |     ]],[[ | ||||||
|       int i[2]; |       int i[2]={0,0}; | ||||||
|       int j = rand(i[0]); |       int j = rand(i[0]); | ||||||
|       if(j) |       if(j) | ||||||
|         return j; |         return j; | ||||||
|   | |||||||
| @@ -70,6 +70,17 @@ $   write sys$output "Can not find VMS specific Curl readme file." | |||||||
| $   goto all_exit | $   goto all_exit | ||||||
| $ endif | $ 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. "" | $ if f$search("sys$disk:[]hp_ssl_release_info.txt") .eqs. "" | ||||||
| $ then | $ then | ||||||
| $   write sys$output "GNV_LINK_CURL.COM has not been run!" | $   write sys$output "GNV_LINK_CURL.COM has not been run!" | ||||||
| @@ -77,6 +88,7 @@ $   goto all_exit | |||||||
| $ endif | $ endif | ||||||
| $! | $! | ||||||
| $ type/noheader 'curl_readme', 'vms_readme', - | $ type/noheader 'curl_readme', 'vms_readme', - | ||||||
|  |                 'curl_release_notes', - | ||||||
|                 sys$disk:[]curl_release_note_start.txt, - |                 sys$disk:[]curl_release_note_start.txt, - | ||||||
|                 sys$disk:[]hp_ssl_release_info.txt, - |                 sys$disk:[]hp_ssl_release_info.txt, - | ||||||
|                 'curl_copying', - |                 '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;* | $   if f$search("''file'.opt") .nes. "" then delete/log 'file'.opt;* | ||||||
| $   file = "[...]curl-*_original_src.bck" | $   file = "[...]curl-*_original_src.bck" | ||||||
| $   if f$search(file) .nes. "" then delete/log 'file';* | $   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" | $   file = "[...]curl-*_vms_src.bck" | ||||||
| $   if f$search(file) .nes. "" then delete/log 'file';* | $   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" | $   file = "[...]curl-*.release_notes" | ||||||
| $   if f$search(file) .nes. "" then delete/log 'file';* | $   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" | $   file = "[...]*curl*.pcsi$desc" | ||||||
| $   if f$search(file) .nes. "" then delete/log 'file';* | $   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" | $   file = "[...]*curl*.pcsi$text" | ||||||
| $   if f$search(file) .nes. "" then delete/log 'file';* | $   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 | $   if clean_all .eq. 0 then goto Common_Exit | ||||||
| $ endif | $ endif | ||||||
|   | |||||||
| @@ -108,15 +108,36 @@ $! | |||||||
| $ file = "lcl_root:[.include.curl]curlbuild.h_old" | $ file = "lcl_root:[.include.curl]curlbuild.h_old" | ||||||
| $ if f$search(file) .nes. "" then delete 'file';* | $ 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" | $ file = "lcl_root:[.packages.vms]curl-*.release_notes" | ||||||
| $ if f$search(file) .nes. "" then delete 'file';* | $ 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" | $ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$desc" | ||||||
| $ if f$search(file) .nes. "" then delete 'file';* | $ 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" | $ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$text" | ||||||
| $ if f$search(file) .nes. "" then delete 'file';* | $ 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 | $ 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->proxyuserpwd); | ||||||
|   Curl_safefree(config->proxy); |   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->noproxy); | ||||||
|  |  | ||||||
|   Curl_safefree(config->mail_from); |   Curl_safefree(config->mail_from); | ||||||
| @@ -96,6 +101,8 @@ void free_config_fields(struct Configurable *config) | |||||||
|   Curl_safefree(config->krblevel); |   Curl_safefree(config->krblevel); | ||||||
|   Curl_safefree(config->trace_dump); |   Curl_safefree(config->trace_dump); | ||||||
|  |  | ||||||
|  |   Curl_safefree(config->xoauth2_bearer); | ||||||
|  |  | ||||||
|   config->trace_stream = NULL; /* closed elsewhere when appropriate */ |   config->trace_stream = NULL; /* closed elsewhere when appropriate */ | ||||||
|  |  | ||||||
|   Curl_safefree(config->writeout); |   Curl_safefree(config->writeout); | ||||||
| @@ -125,4 +132,3 @@ void free_config_fields(struct Configurable *config) | |||||||
|  |  | ||||||
|   Curl_safefree(config->libcurl); |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -66,6 +66,10 @@ struct Configurable { | |||||||
|   char *range; |   char *range; | ||||||
|   long low_speed_limit; |   long low_speed_limit; | ||||||
|   long low_speed_time; |   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 |   int showerror; /* -1 == unset, default => show errors | ||||||
|                     0 => -s is used to NOT show errors |                     0 => -s is used to NOT show errors | ||||||
|                     1 => -S has been used to 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 */ |   bool use_metalink;        /* process given URLs as metalink XML file */ | ||||||
|   metalinkfile *metalinkfile_list; /* point to the first node */ |   metalinkfile *metalinkfile_list; /* point to the first node */ | ||||||
|   metalinkfile *metalinkfile_last; /* point to the last/current 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 */ | }; /* struct Configurable */ | ||||||
|  |  | ||||||
| void free_config_fields(struct Configurable *config); | void free_config_fields(struct Configurable *config); | ||||||
|  |  | ||||||
| #endif /* HEADER_CURL_TOOL_CFGABLE_H */ | #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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * 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* |   /* all these ones, starting with "*" or "$" as a short-option have *no* | ||||||
|      short option to mention. */ |      short option to mention. */ | ||||||
|   {"*",  "url",                      TRUE}, |   {"*",  "url",                      TRUE}, | ||||||
|  |   {"*4", "dns-ipv4-addr",            TRUE}, | ||||||
|  |   {"*6", "dns-ipv6-addr",            TRUE}, | ||||||
|   {"*a", "random-file",              TRUE}, |   {"*a", "random-file",              TRUE}, | ||||||
|   {"*b", "egd-file",                 TRUE}, |   {"*b", "egd-file",                 TRUE}, | ||||||
|  |   {"*B", "oauth2-bearer",             TRUE}, | ||||||
|   {"*c", "connect-timeout",          TRUE}, |   {"*c", "connect-timeout",          TRUE}, | ||||||
|   {"*d", "ciphers",                  TRUE}, |   {"*d", "ciphers",                  TRUE}, | ||||||
|  |   {"*D", "dns-interface",            TRUE}, | ||||||
|   {"*e", "disable-epsv",             FALSE}, |   {"*e", "disable-epsv",             FALSE}, | ||||||
|   {"*E", "epsv",                     FALSE}, |   {"*E", "epsv",                     FALSE}, | ||||||
|          /* 'epsv' made like this to make --no-epsv and --epsv to work |          /* 'epsv' made like this to make --no-epsv and --epsv to work | ||||||
| @@ -84,6 +88,7 @@ static const struct LongShort aliases[]= { | |||||||
| #ifdef USE_ENVIRONMENT | #ifdef USE_ENVIRONMENT | ||||||
|   {"*f", "environment",              FALSE}, |   {"*f", "environment",              FALSE}, | ||||||
| #endif | #endif | ||||||
|  |   {"*F", "dns-servers",              TRUE}, | ||||||
|   {"*g", "trace",                    TRUE}, |   {"*g", "trace",                    TRUE}, | ||||||
|   {"*h", "trace-ascii",              TRUE}, |   {"*h", "trace-ascii",              TRUE}, | ||||||
|   {"*i", "limit-rate",               TRUE}, |   {"*i", "limit-rate",               TRUE}, | ||||||
| @@ -174,7 +179,10 @@ static const struct LongShort aliases[]= { | |||||||
|   {"$I", "post303",                  FALSE}, |   {"$I", "post303",                  FALSE}, | ||||||
|   {"$J", "metalink",                 FALSE}, |   {"$J", "metalink",                 FALSE}, | ||||||
|   {"$K", "sasl-ir",                  FALSE}, |   {"$K", "sasl-ir",                  FALSE}, | ||||||
|  |   {"$L", "test-event",               FALSE}, | ||||||
|   {"0",   "http1.0",                 FALSE}, |   {"0",   "http1.0",                 FALSE}, | ||||||
|  |   {"01",  "http1.1",                 FALSE}, | ||||||
|  |   {"02",  "http2.0",                 FALSE}, | ||||||
|   {"1",  "tlsv1",                    FALSE}, |   {"1",  "tlsv1",                    FALSE}, | ||||||
|   {"2",  "sslv2",                    FALSE}, |   {"2",  "sslv2",                    FALSE}, | ||||||
|   {"3",  "sslv3",                    FALSE}, |   {"3",  "sslv3",                    FALSE}, | ||||||
| @@ -283,7 +291,8 @@ static const struct feat feats[] = { | |||||||
|   {"krb4",           CURL_VERSION_KERBEROS4}, |   {"krb4",           CURL_VERSION_KERBEROS4}, | ||||||
|   {"libz",           CURL_VERSION_LIBZ}, |   {"libz",           CURL_VERSION_LIBZ}, | ||||||
|   {"CharConv",       CURL_VERSION_CONV}, |   {"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. | /* 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) { |     switch(letter) { | ||||||
|     case '*': /* options without a short option */ |     case '*': /* options without a short option */ | ||||||
|       switch(subletter) { |       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 */ |       case 'a': /* random-file */ | ||||||
|         GetStr(&config->random_file, nextarg); |         GetStr(&config->random_file, nextarg); | ||||||
|         break; |         break; | ||||||
|       case 'b': /* egd-file */ |       case 'b': /* egd-file */ | ||||||
|         GetStr(&config->egd_file, nextarg); |         GetStr(&config->egd_file, nextarg); | ||||||
|         break; |         break; | ||||||
|  |       case 'B': /* XOAUTH2 Bearer */ | ||||||
|  |         GetStr(&config->xoauth2_bearer, nextarg); | ||||||
|  |         break; | ||||||
|       case 'c': /* connect-timeout */ |       case 'c': /* connect-timeout */ | ||||||
|         err = str2udouble(&config->connecttimeout, nextarg); |         err = str2udouble(&config->connecttimeout, nextarg); | ||||||
|         if(err) |         if(err) | ||||||
| @@ -505,6 +525,10 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|       case 'd': /* ciphers */ |       case 'd': /* ciphers */ | ||||||
|         GetStr(&config->cipher_list, nextarg); |         GetStr(&config->cipher_list, nextarg); | ||||||
|         break; |         break; | ||||||
|  |       case 'D': /* --dns-interface */ | ||||||
|  |         /* interface name */ | ||||||
|  |         GetStr(&config->dns_interface, nextarg); | ||||||
|  |         break; | ||||||
|       case 'e': /* --disable-epsv */ |       case 'e': /* --disable-epsv */ | ||||||
|         config->disable_epsv = toggle; |         config->disable_epsv = toggle; | ||||||
|         break; |         break; | ||||||
| @@ -516,6 +540,10 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|         config->writeenv = toggle; |         config->writeenv = toggle; | ||||||
|         break; |         break; | ||||||
| #endif | #endif | ||||||
|  |       case 'F': /* --dns-servers */ | ||||||
|  |         /* IP addrs of DNS servers */ | ||||||
|  |         GetStr(&config->dns_servers, nextarg); | ||||||
|  |         break; | ||||||
|       case 'g': /* --trace */ |       case 'g': /* --trace */ | ||||||
|         GetStr(&config->trace_dump, nextarg); |         GetStr(&config->trace_dump, nextarg); | ||||||
|         if(config->tracetype && (config->tracetype != TRACE_BIN)) |         if(config->tracetype && (config->tracetype != TRACE_BIN)) | ||||||
| @@ -639,7 +667,7 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case 'r': /* --create-dirs */ |       case 'r': /* --create-dirs */ | ||||||
|         config->create_dirs = TRUE; |         config->create_dirs = toggle; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case 's': /* --max-redirs */ |       case 's': /* --max-redirs */ | ||||||
| @@ -661,7 +689,7 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|  |  | ||||||
|       case 'u': /* --crlf */ |       case 'u': /* --crlf */ | ||||||
|         /* LF -> CRLF conversion? */ |         /* LF -> CRLF conversion? */ | ||||||
|         config->crlf = TRUE; |         config->crlf = toggle; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case 'v': /* --stderr */ |       case 'v': /* --stderr */ | ||||||
| @@ -888,7 +916,7 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|         GetStr(&config->socks5_gssapi_service, nextarg); |         GetStr(&config->socks5_gssapi_service, nextarg); | ||||||
|         break; |         break; | ||||||
|       case '7': /* --socks5-gssapi-nec*/ |       case '7': /* --socks5-gssapi-nec*/ | ||||||
|         config->socks5_gssapi_nec = TRUE; |         config->socks5_gssapi_nec = toggle; | ||||||
|         break; |         break; | ||||||
| #endif | #endif | ||||||
|       case '8': /* --proxy1.0 */ |       case '8': /* --proxy1.0 */ | ||||||
| @@ -959,7 +987,14 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|       case 'K': /* --sasl-ir */ |       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; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
| @@ -972,10 +1007,22 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|     case '~': /* --xattr */ |     case '~': /* --xattr */ | ||||||
|       config->xattr = toggle; |       config->xattr = toggle; | ||||||
|       break; |       break; | ||||||
|     case '0': |     case '0': /* --http* options */ | ||||||
|  |       switch(subletter) { | ||||||
|  |       case '\0': | ||||||
|         /* HTTP version 1.0 */ |         /* HTTP version 1.0 */ | ||||||
|         config->httpversion = CURL_HTTP_VERSION_1_0; |         config->httpversion = CURL_HTTP_VERSION_1_0; | ||||||
|         break; |         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': |     case '1': | ||||||
|       /* TLS version 1 */ |       /* TLS version 1 */ | ||||||
|       config->ssl_version = CURL_SSLVERSION_TLSv1; |       config->ssl_version = CURL_SSLVERSION_TLSv1; | ||||||
| @@ -1621,20 +1668,14 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
|     case 'u': |     case 'u': | ||||||
|       /* user:password  */ |       /* user:password;options  */ | ||||||
|       GetStr(&config->userpwd, nextarg); |       GetStr(&config->userpwd, nextarg); | ||||||
|       cleanarg(nextarg); |       cleanarg(nextarg); | ||||||
|       err = checkpasswd("host", &config->userpwd); |  | ||||||
|       if(err) |  | ||||||
|         return err; |  | ||||||
|       break; |       break; | ||||||
|     case 'U': |     case 'U': | ||||||
|       /* Proxy user:password  */ |       /* Proxy user:password  */ | ||||||
|       GetStr(&config->proxyuserpwd, nextarg); |       GetStr(&config->proxyuserpwd, nextarg); | ||||||
|       cleanarg(nextarg); |       cleanarg(nextarg); | ||||||
|       err = checkpasswd("proxy", &config->proxyuserpwd); |  | ||||||
|       if(err) |  | ||||||
|         return err; |  | ||||||
|       break; |       break; | ||||||
|     case 'v': |     case 'v': | ||||||
|       if(toggle) { |       if(toggle) { | ||||||
| @@ -1781,4 +1822,3 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */ | |||||||
|  |  | ||||||
|   return PARAM_OK; |   return PARAM_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -69,6 +69,10 @@ static const char *const helptext[] = { | |||||||
|   "     --digest        Use HTTP Digest Authentication (H)", |   "     --digest        Use HTTP Digest Authentication (H)", | ||||||
|   "     --disable-eprt  Inhibit using EPRT or LPRT (F)", |   "     --disable-eprt  Inhibit using EPRT or LPRT (F)", | ||||||
|   "     --disable-epsv  Inhibit using EPSV (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", |   " -D, --dump-header FILE  Write the headers to this file", | ||||||
|   "     --egd-file FILE  EGD socket path for random data (SSL)", |   "     --egd-file FILE  EGD socket path for random data (SSL)", | ||||||
|   "     --engine ENGINE  Crypto engine (SSL). \"--engine list\" for list", |   "     --engine ENGINE  Crypto engine (SSL). \"--engine list\" for list", | ||||||
| @@ -99,6 +103,8 @@ static const char *const helptext[] = { | |||||||
|   "     --hostpubmd5 MD5  " |   "     --hostpubmd5 MD5  " | ||||||
|   "Hex encoded MD5 string of the host public key. (SSH)", |   "Hex encoded MD5 string of the host public key. (SSH)", | ||||||
|   " -0, --http1.0       Use HTTP 1.0 (H)", |   " -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", |   "     --ignore-content-length  Ignore the HTTP Content-Length header", | ||||||
|   " -i, --include       Include protocol headers in the output (H/F)", |   " -i, --include       Include protocol headers in the output (H/F)", | ||||||
|   " -k, --insecure      Allow connections to SSL sites without certs (H)", |   " -k, --insecure      Allow connections to SSL sites without certs (H)", | ||||||
| @@ -119,9 +125,9 @@ static const char *const helptext[] = { | |||||||
|   " -L, --location      Follow redirects (H)", |   " -L, --location      Follow redirects (H)", | ||||||
|   "     --location-trusted like --location and send auth to other hosts (H)", |   "     --location-trusted like --location and send auth to other hosts (H)", | ||||||
|   " -M, --manual        Display the full manual", |   " -M, --manual        Display the full manual", | ||||||
|   "     --mail-from FROM  Mail from this address", |   "     --mail-from FROM  Mail from this address (SMTP)", | ||||||
|   "     --mail-rcpt TO  Mail to this receiver(s)", |   "     --mail-rcpt TO  Mail to this/these addresses (SMTP)", | ||||||
|   "     --mail-auth AUTH  Originator address of the original email", |   "     --mail-auth AUTH  Originator address of the original email (SMTP)", | ||||||
|   "     --max-filesize BYTES  Maximum file size to download (H/F)", |   "     --max-filesize BYTES  Maximum file size to download (H/F)", | ||||||
|   "     --max-redirs NUM  Maximum number of redirects allowed (H)", |   "     --max-redirs NUM  Maximum number of redirects allowed (H)", | ||||||
|   " -m, --max-time SECONDS  Maximum time allowed for the transfer", |   " -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)", |   "     --no-sessionid  Disable SSL session-ID reusing (SSL)", | ||||||
|   "     --noproxy       List of hosts which do not use proxy", |   "     --noproxy       List of hosts which do not use proxy", | ||||||
|   "     --ntlm          Use HTTP NTLM authentication (H)", |   "     --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", |   " -o, --output FILE   Write output to <file> instead of stdout", | ||||||
|   "     --pass PASS     Pass phrase for the private key (SSL/SSH)", |   "     --pass PASS     Pass phrase for the private key (SSL/SSH)", | ||||||
|   "     --post301       " |   "     --post301       " | ||||||
| @@ -173,7 +180,7 @@ static const char *const helptext[] = { | |||||||
|   "     --retry-delay SECONDS " |   "     --retry-delay SECONDS " | ||||||
|   "When retrying, wait this many seconds between each", |   "When retrying, wait this many seconds between each", | ||||||
|   "     --retry-max-time SECONDS  Retry only within this period", |   "     --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    " |   " -S, --show-error    " | ||||||
|   "Show error. With -s, make curl show errors when they occur", |   "Show error. With -s, make curl show errors when they occur", | ||||||
|   " -s, --silent        Silent mode. Don't output anything", |   " -s, --silent        Silent mode. Don't output anything", | ||||||
| @@ -243,4 +250,3 @@ void tool_help(void) | |||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -69,6 +69,7 @@ | |||||||
| #include "tool_msgs.h" | #include "tool_msgs.h" | ||||||
| #include "tool_operate.h" | #include "tool_operate.h" | ||||||
| #include "tool_operhlp.h" | #include "tool_operhlp.h" | ||||||
|  | #include "tool_paramhlp.h" | ||||||
| #include "tool_parsecfg.h" | #include "tool_parsecfg.h" | ||||||
| #include "tool_setopt.h" | #include "tool_setopt.h" | ||||||
| #include "tool_sleep.h" | #include "tool_sleep.h" | ||||||
| @@ -81,6 +82,11 @@ | |||||||
|  |  | ||||||
| #include "memdebug.h" /* keep this as LAST include */ | #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_--" | #define CURLseparator  "--_curl_--" | ||||||
|  |  | ||||||
| #ifndef O_BINARY | #ifndef O_BINARY | ||||||
| @@ -196,6 +202,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) | |||||||
|   bool stillflags; |   bool stillflags; | ||||||
|   int res = 0; |   int res = 0; | ||||||
|   int i; |   int i; | ||||||
|  |   unsigned long li; | ||||||
|  |  | ||||||
|   bool orig_noprogress; |   bool orig_noprogress; | ||||||
|   bool orig_isatty; |   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) { |   if((!config->url_list || !config->url_list->url) && !config->list_engines) { | ||||||
|     helpf(config->errors, "no URL specified!\n"); |     helpf(config->errors, "no URL specified!\n"); | ||||||
|     res = CURLE_FAILED_INIT; |     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) { |   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 *infiles; /* might be a glob pattern */ | ||||||
|     char *outfiles; |     char *outfiles; | ||||||
|     int infilenum; |     unsigned long infilenum; | ||||||
|     URLGlob *inglob; |     URLGlob *inglob; | ||||||
|  |  | ||||||
|     int metalink = 0; /* nonzero for metalink download. */ |     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 */ |       char *uploadfile; /* a single file, never a glob */ | ||||||
|       int separator; |       int separator; | ||||||
|       URLGlob *urls; |       URLGlob *urls; | ||||||
|       int urlnum; |       unsigned long urlnum; | ||||||
|  |  | ||||||
|       uploadfile = NULL; |       uploadfile = NULL; | ||||||
|       urls = 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); |       separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1); | ||||||
|  |  | ||||||
|       /* Here's looping around each globbed URL */ |       /* Here's looping around each globbed URL */ | ||||||
|       for(i = 0 ; i < urlnum; i++) { |       for(li = 0 ; li < urlnum; li++) { | ||||||
|  |  | ||||||
|         int infd; |         int infd; | ||||||
|         bool infdopen; |         bool infdopen; | ||||||
| @@ -628,7 +647,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) | |||||||
|             if(res) |             if(res) | ||||||
|               goto show_error; |               goto show_error; | ||||||
|           } |           } | ||||||
|           else if(!i) { |           else if(!li) { | ||||||
|             this_url = strdup(urlnode->url); |             this_url = strdup(urlnode->url); | ||||||
|             if(!this_url) { |             if(!this_url) { | ||||||
|               res = CURLE_OUT_OF_MEMORY; |               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)) { |         if(urlnum > 1 && !(config->mute)) { | ||||||
|           fprintf(config->errors, "\n[%d/%d]: %s --> %s\n", |           fprintf(config->errors, "\n[%lu/%lu]: %s --> %s\n", | ||||||
|                   i+1, urlnum, this_url, outfile ? outfile : "<stdout>"); |                   li+1, urlnum, this_url, outfile ? outfile : "<stdout>"); | ||||||
|           if(separator) |           if(separator) | ||||||
|             printf("%s%s\n", CURLseparator, this_url); |             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) |         else if(!config->use_metalink) | ||||||
|           my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L); |           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) | #if !defined(CURL_DISABLE_PROXY) | ||||||
|         { |         { | ||||||
|           /* TODO: Make this a run-time check instead of compile-time one. */ |           /* 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); |           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: */ |         /* new in libcurl 7.6.2: */ | ||||||
|         my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); |         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); |                     mlfile->filename, this_url); | ||||||
| #endif /* USE_METALINK */ | #endif /* USE_METALINK */ | ||||||
|  |  | ||||||
|  | #ifdef CURLDEBUG | ||||||
|  |           if(config->test_event_based) | ||||||
|  |             res = curl_easy_perform_ev(curl); | ||||||
|  |           else | ||||||
|  | #endif | ||||||
|           res = curl_easy_perform(curl); |           res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|           if(outs.is_cd_filename && outs.stream && !config->mute && |           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; |   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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -31,141 +31,146 @@ | |||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|   GLOB_OK, |   GLOB_OK, | ||||||
|   GLOB_NO_MEM, |   GLOB_NO_MEM = CURLE_OUT_OF_MEMORY, | ||||||
|   GLOB_ERROR |   GLOB_ERROR = CURLE_URL_MALFORMAT | ||||||
| } GlobCode; | } GlobCode; | ||||||
|  |  | ||||||
| /* | #define GLOBERROR(string, column, code) \ | ||||||
|  * glob_word() |   glob->error = string, glob->pos = column, code; | ||||||
|  * |  | ||||||
|  * 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 */ |  | ||||||
|  |  | ||||||
| static GlobCode glob_set(URLGlob *glob, char *pattern, | void glob_cleanup(URLGlob* glob); | ||||||
|                          size_t pos, int *amount) |  | ||||||
|  | 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 '{' |   /* processes a set expression with the point behind the opening '{' | ||||||
|      ','-separated elements are collected until the next closing '}' |      ','-separated elements are collected until the next closing '}' | ||||||
|   */ |   */ | ||||||
|   URLPattern *pat; |   URLPattern *pat; | ||||||
|   GlobCode res; |  | ||||||
|   bool done = FALSE; |   bool done = FALSE; | ||||||
|   char *buf = glob->glob_buffer; |   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,... */ |   /* patterns 0,1,2,... correspond to size=1,3,5,... */ | ||||||
|   pat->type = UPTSet; |   pat->type = UPTSet; | ||||||
|   pat->content.Set.size = 0; |   pat->content.Set.size = 0; | ||||||
|   pat->content.Set.ptr_s = 0; |   pat->content.Set.ptr_s = 0; | ||||||
|   pat->content.Set.elements = NULL; |   pat->content.Set.elements = NULL; | ||||||
|  |   pat->globindex = globindex; | ||||||
|   if(++glob->size > (GLOB_PATTERN_NUM*2)) { |  | ||||||
|     snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n"); |  | ||||||
|     return GLOB_ERROR; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   while(!done) { |   while(!done) { | ||||||
|     switch (*pattern) { |     switch (*pattern) { | ||||||
|     case '\0':                  /* URL ended while set was still open */ |     case '\0':                  /* URL ended while set was still open */ | ||||||
|       snprintf(glob->errormsg, sizeof(glob->errormsg), |       return GLOBERROR("unmatched brace", opos, GLOB_ERROR); | ||||||
|                "unmatched brace at pos %zu\n", pos); |  | ||||||
|       return GLOB_ERROR; |  | ||||||
|  |  | ||||||
|     case '{': |     case '{': | ||||||
|     case '[':                   /* no nested expressions at this time */ |     case '[':                   /* no nested expressions at this time */ | ||||||
|       snprintf(glob->errormsg, sizeof(glob->errormsg), |       return GLOBERROR("nested brace", *posp, GLOB_ERROR); | ||||||
|                "nested braces not supported at pos %zu\n", pos); |  | ||||||
|       return GLOB_ERROR; |  | ||||||
|  |  | ||||||
|     case ',': |  | ||||||
|     case '}':                           /* set element completed */ |     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'; |       *buf = '\0'; | ||||||
|       if(pat->content.Set.elements) { |       if(pat->content.Set.elements) { | ||||||
|         char **new_arr = realloc(pat->content.Set.elements, |         char **new_arr = realloc(pat->content.Set.elements, | ||||||
|                                  (pat->content.Set.size + 1) * sizeof(char*)); |                                  (pat->content.Set.size + 1) * sizeof(char*)); | ||||||
|         if(!new_arr) { |         if(!new_arr) | ||||||
|           short elem; |           return GLOBERROR("out of memory", 0, GLOB_NO_MEM); | ||||||
|           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; |  | ||||||
|         } |  | ||||||
|         pat->content.Set.elements = new_arr; |         pat->content.Set.elements = new_arr; | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|         pat->content.Set.elements = malloc(sizeof(char*)); |         pat->content.Set.elements = malloc(sizeof(char*)); | ||||||
|       if(!pat->content.Set.elements) { |  | ||||||
|         snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); |       if(!pat->content.Set.elements) | ||||||
|         return GLOB_NO_MEM; |         return GLOBERROR("out of memory", 0, GLOB_NO_MEM); | ||||||
|       } |  | ||||||
|       pat->content.Set.elements[pat->content.Set.size] = |       pat->content.Set.elements[pat->content.Set.size] = | ||||||
|         strdup(glob->glob_buffer); |         strdup(glob->glob_buffer); | ||||||
|       if(!pat->content.Set.elements[pat->content.Set.size]) { |       if(!pat->content.Set.elements[pat->content.Set.size]) | ||||||
|         short elem; |         return GLOBERROR("out of memory", 0, GLOB_NO_MEM); | ||||||
|         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; |  | ||||||
|       } |  | ||||||
|       ++pat->content.Set.size; |       ++pat->content.Set.size; | ||||||
|  |  | ||||||
|       if(*pattern == '}') { |       if(*pattern == '}') { | ||||||
|         /* entire set pattern completed */ |         pattern++; /* pass the closing brace */ | ||||||
|         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; |  | ||||||
|  |  | ||||||
|         done = TRUE; |         done = TRUE; | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       buf = glob->glob_buffer; |       buf = glob->glob_buffer; | ||||||
|       ++pattern; |       ++pattern; | ||||||
|       ++pos; |       ++(*posp); | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case ']':                           /* illegal closing bracket */ |     case ']':                           /* illegal closing bracket */ | ||||||
|       snprintf(glob->errormsg, sizeof(glob->errormsg), |       return GLOBERROR("unexpected close bracket", *posp, GLOB_ERROR); | ||||||
|                "illegal pattern at pos %zu\n", pos); |  | ||||||
|       return GLOB_ERROR; |  | ||||||
|  |  | ||||||
|     case '\\':                          /* escaped character, skip '\' */ |     case '\\':                          /* escaped character, skip '\' */ | ||||||
|       if(pattern[1]) { |       if(pattern[1]) { | ||||||
|         ++pattern; |         ++pattern; | ||||||
|         ++pos; |         ++(*posp); | ||||||
|       } |       } | ||||||
|       /* intentional fallthrough */ |       /* intentional fallthrough */ | ||||||
|     default: |     default: | ||||||
|       *buf++ = *pattern++;              /* copy character to set element */ |       *buf++ = *pattern++;              /* copy character to set element */ | ||||||
|       ++pos; |       ++(*posp); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   *patternp = pattern; /* return with the new position */ | ||||||
|   return GLOB_OK; |   return GLOB_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static GlobCode glob_range(URLGlob *glob, char *pattern, | static GlobCode glob_range(URLGlob *glob, char **patternp, | ||||||
|                            size_t pos, int *amount) |                            size_t *posp, unsigned long *amount, | ||||||
|  |                            int globindex) | ||||||
| { | { | ||||||
|   /* processes a range expression with the point behind the opening '[' |   /* processes a range expression with the point behind the opening '[' | ||||||
|      - char range: e.g. "a-z]", "B-Q]" |      - char range: e.g. "a-z]", "B-Q]" | ||||||
| @@ -174,77 +179,68 @@ static GlobCode glob_range(URLGlob *glob, char *pattern, | |||||||
|      expression is checked for well-formedness and collected until the next ']' |      expression is checked for well-formedness and collected until the next ']' | ||||||
|   */ |   */ | ||||||
|   URLPattern *pat; |   URLPattern *pat; | ||||||
|   char *c; |  | ||||||
|   char sep; |  | ||||||
|   char sep2; |  | ||||||
|   int step; |  | ||||||
|   int rc; |   int rc; | ||||||
|   GlobCode res; |   char *pattern = *patternp; | ||||||
|   int wordamount = 1; |   char *c; | ||||||
|  |  | ||||||
|   pat = &glob->pattern[glob->size / 2]; |   pat = &glob->pattern[glob->size]; | ||||||
|   /* patterns 0,1,2,... correspond to size=1,3,5,... */ |   pat->globindex = globindex; | ||||||
|   if(++glob->size > (GLOB_PATTERN_NUM*2)) { |  | ||||||
|     snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n"); |  | ||||||
|     return GLOB_ERROR; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if(ISALPHA(*pattern)) { |   if(ISALPHA(*pattern)) { | ||||||
|     /* character range detected */ |     /* character range detected */ | ||||||
|     char min_c; |     char min_c; | ||||||
|     char max_c; |     char max_c; | ||||||
|  |     int step=1; | ||||||
|  |  | ||||||
|     pat->type = UPTCharRange; |     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 */ |       /* the pattern is not well-formed */ | ||||||
|       snprintf(glob->errormsg, sizeof(glob->errormsg), |       return GLOBERROR("bad range", *posp, GLOB_ERROR); | ||||||
|                "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; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* if there was a ":[num]" thing, use that as step or else use 1 */ |     /* if there was a ":[num]" thing, use that as step or else use 1 */ | ||||||
|     pat->content.CharRange.step = |     pat->content.CharRange.step = step; | ||||||
|       ((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1; |  | ||||||
|  |  | ||||||
|     pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c; |     pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c; | ||||||
|     pat->content.CharRange.max_c = max_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)) { |   else if(ISDIGIT(*pattern)) { | ||||||
|     /* numeric range detected */ |     /* numeric range detected */ | ||||||
|     int min_n; |     unsigned long min_n; | ||||||
|     int max_n; |     unsigned long max_n = 0; | ||||||
|  |     unsigned long step_n = 0; | ||||||
|  |     char *endp; | ||||||
|  |  | ||||||
|     pat->type = UPTNumRange; |     pat->type = UPTNumRange; | ||||||
|     pat->content.NumRange.padlength = 0; |     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') { |     if(*pattern == '0') { | ||||||
|       /* leading zero specified */ |       /* leading zero specified, count them! */ | ||||||
|       c = pattern; |       c = pattern; | ||||||
|       while(ISDIGIT(*c)) { |       while(ISDIGIT(*c)) { | ||||||
|         c++; |         c++; | ||||||
| @@ -252,59 +248,74 @@ static GlobCode glob_range(URLGlob *glob, char *pattern, | |||||||
|                                               instances of this pattern */ |                                               instances of this pattern */ | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |  | ||||||
|  |     errno = 0; | ||||||
|  |     min_n = strtoul(pattern, &endp, 10); | ||||||
|  |     if(errno || (endp == pattern)) | ||||||
|  |       endp=NULL; | ||||||
|     else { |     else { | ||||||
|     snprintf(glob->errormsg, sizeof(glob->errormsg), |       if(*endp != '-') | ||||||
|              "illegal character in range specification at pos %zu\n", pos); |         endp = NULL; | ||||||
|     return GLOB_ERROR; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   c = (char*)strchr(pattern, ']'); /* continue after next ']' */ |  | ||||||
|   if(c) |  | ||||||
|     c++; |  | ||||||
|       else { |       else { | ||||||
|     snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'"); |         pattern = endp+1; | ||||||
|     return GLOB_ERROR; /* missing ']' */ |         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 |         else | ||||||
|       *amount = wordamount * (pat->content.NumRange.max_n - |           step_n = 1; | ||||||
|                               pat->content.NumRange.min_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, | static GlobCode glob_parse(URLGlob *glob, char *pattern, | ||||||
|                           size_t pos, int *amount) |                            size_t pos, unsigned long *amount) | ||||||
| { | { | ||||||
|   /* processes a literal string component of a URL |   /* processes a literal string component of a URL | ||||||
|      special characters '{' and '[' branch to set/range processing functions |      special characters '{' and '[' branch to set/range processing functions | ||||||
|    */ |    */ | ||||||
|   char* buf = glob->glob_buffer; |   char* buf = glob->glob_buffer; | ||||||
|   size_t litindex; |  | ||||||
|   GlobCode res = GLOB_OK; |   GlobCode res = GLOB_OK; | ||||||
|  |   int globindex = 0; /* count "actual" globs */ | ||||||
|  |  | ||||||
|   *amount = 1; /* default is one single string */ |   while(*pattern && !res) { | ||||||
|  |     int sublen = 0; | ||||||
|   while(*pattern != '\0' && *pattern != '{' && *pattern != '[') { |     while(*pattern && *pattern != '{' && *pattern != '[') { | ||||||
|     if(*pattern == '}' || *pattern == ']') { |       if(*pattern == '}' || *pattern == ']') | ||||||
|       snprintf(glob->errormsg, sizeof(glob->errormsg), |         return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR); | ||||||
|                "unmatched close brace/bracket at pos %zu\n", pos); |  | ||||||
|       return GLOB_ERROR; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|       /* only allow \ to escape known "special letters" */ |       /* only allow \ to escape known "special letters" */ | ||||||
|       if(*pattern == '\\' && |       if(*pattern == '\\' && | ||||||
| @@ -317,47 +328,51 @@ static GlobCode glob_word(URLGlob *glob, char *pattern, | |||||||
|       } |       } | ||||||
|       *buf++ = *pattern++; /* copy character to literal */ |       *buf++ = *pattern++; /* copy character to literal */ | ||||||
|       ++pos; |       ++pos; | ||||||
|  |       sublen++; | ||||||
|     } |     } | ||||||
|  |     if(sublen) { | ||||||
|  |       /* we got a literal string, add it as a single-item list */ | ||||||
|       *buf = '\0'; |       *buf = '\0'; | ||||||
|   litindex = glob->size / 2; |       res = glob_fixed(glob, amount); | ||||||
|   /* 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; |  | ||||||
|     } |     } | ||||||
|   ++glob->size; |     else { | ||||||
|  |       if(!*amount) | ||||||
|  |         *amount = 1; | ||||||
|  |  | ||||||
|       switch (*pattern) { |       switch (*pattern) { | ||||||
|   case '\0': |       case '\0': /* done  */ | ||||||
|     /* singular URL processed  */ |  | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case '{': |       case '{': | ||||||
|         /* process set pattern */ |         /* process set pattern */ | ||||||
|     res = glob_set(glob, ++pattern, ++pos, amount); |         pattern++; | ||||||
|  |         pos++; | ||||||
|  |         res = glob_set(glob, &pattern, &pos, amount, globindex++); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case '[': |       case '[': | ||||||
|         /* process range pattern */ |         /* process range pattern */ | ||||||
|     res = glob_range(glob, ++pattern, ++pos, amount); |         pattern++; | ||||||
|  |         pos++; | ||||||
|  |         res = glob_range(glob, &pattern, &pos, amount, globindex++); | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|   if(res) |     if(++glob->size > GLOB_PATTERN_NUM) | ||||||
|     Curl_safefree(glob->literal[litindex]); |       return GLOBERROR("too many globs", pos, GLOB_ERROR); | ||||||
|  |   } | ||||||
|   return res; |   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 |    * We can deal with any-size, just make a buffer with the same length | ||||||
|    * as the specified URL! |    * as the specified URL! | ||||||
|    */ |    */ | ||||||
|   URLGlob *glob_expand; |   URLGlob *glob_expand; | ||||||
|   int amount; |   unsigned long amount = 0; | ||||||
|   char *glob_buffer; |   char *glob_buffer; | ||||||
|   GlobCode res; |   GlobCode res; | ||||||
|  |  | ||||||
| @@ -372,26 +387,31 @@ int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error) | |||||||
|     Curl_safefree(glob_buffer); |     Curl_safefree(glob_buffer); | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|   } |   } | ||||||
|   glob_expand->size = 0; |  | ||||||
|   glob_expand->urllen = strlen(url); |   glob_expand->urllen = strlen(url); | ||||||
|   glob_expand->glob_buffer = glob_buffer; |   glob_expand->glob_buffer = glob_buffer; | ||||||
|   glob_expand->beenhere = 0; |  | ||||||
|  |  | ||||||
|   res = glob_word(glob_expand, url, 1, &amount); |   res = glob_parse(glob_expand, url, 1, &amount); | ||||||
|   if(!res) |   if(!res) | ||||||
|     *urlnum = amount; |     *urlnum = amount; | ||||||
|   else { |   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 */ |       /* send error description to the error-stream */ | ||||||
|       fprintf(error, "curl: (%d) [globbing] %s", |       fprintf(error, "curl: (%d) [globbing] %s\n", res, t); | ||||||
|               (res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT, |  | ||||||
|               glob_expand->errormsg); |  | ||||||
|     } |     } | ||||||
|     /* it failed, we cleanup */ |     /* it failed, we cleanup */ | ||||||
|     Curl_safefree(glob_buffer); |     glob_cleanup(glob_expand); | ||||||
|     Curl_safefree(glob_expand); |  | ||||||
|     *urlnum = 1; |     *urlnum = 1; | ||||||
|     return (res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT; |     return res; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   *glob = glob_expand; |   *glob = glob_expand; | ||||||
| @@ -404,19 +424,14 @@ void glob_cleanup(URLGlob* glob) | |||||||
|   int elem; |   int elem; | ||||||
|  |  | ||||||
|   for(i = glob->size - 1; i < glob->size; --i) { |   for(i = glob->size - 1; i < glob->size; --i) { | ||||||
|     if(!(i & 1)) {     /* even indexes contain literals */ |     if((glob->pattern[i].type == UPTSet) && | ||||||
|       Curl_safefree(glob->literal[i/2]); |        (glob->pattern[i].content.Set.elements)) { | ||||||
|     } |       for(elem = glob->pattern[i].content.Set.size - 1; | ||||||
|     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; |  | ||||||
|           elem >= 0; |           elem >= 0; | ||||||
|           --elem) { |           --elem) { | ||||||
|           Curl_safefree(glob->pattern[i/2].content.Set.elements[elem]); |         Curl_safefree(glob->pattern[i].content.Set.elements[elem]); | ||||||
|         } |  | ||||||
|         Curl_safefree(glob->pattern[i/2].content.Set.elements); |  | ||||||
|       } |       } | ||||||
|  |       Curl_safefree(glob->pattern[i].content.Set.elements); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   Curl_safefree(glob->glob_buffer); |   Curl_safefree(glob->glob_buffer); | ||||||
| @@ -426,7 +441,6 @@ void glob_cleanup(URLGlob* glob) | |||||||
| int glob_next_url(char **globbed, URLGlob *glob) | int glob_next_url(char **globbed, URLGlob *glob) | ||||||
| { | { | ||||||
|   URLPattern *pat; |   URLPattern *pat; | ||||||
|   char *lit; |  | ||||||
|   size_t i; |   size_t i; | ||||||
|   size_t j; |   size_t j; | ||||||
|   size_t len; |   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, |     /* implement a counter over the index ranges of all patterns, | ||||||
|        starting with the rightmost pattern */ |        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; |       carry = FALSE; | ||||||
|       pat = &glob->pattern[i]; |       pat = &glob->pattern[i]; | ||||||
|       switch (pat->type) { |       switch (pat->type) { | ||||||
| @@ -480,14 +494,7 @@ int glob_next_url(char **globbed, URLGlob *glob) | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   for(j = 0; j < glob->size; ++j) { |   for(j = 0; j < glob->size; ++j) { | ||||||
|     if(!(j&1)) {              /* every other term (j even) is a literal */ |     pat = &glob->pattern[j]; | ||||||
|       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]; |  | ||||||
|     switch(pat->type) { |     switch(pat->type) { | ||||||
|     case UPTSet: |     case UPTSet: | ||||||
|       if(pat->content.Set.elements) { |       if(pat->content.Set.elements) { | ||||||
| @@ -502,7 +509,7 @@ int glob_next_url(char **globbed, URLGlob *glob) | |||||||
|       *buf++ = pat->content.CharRange.ptr_c; |       *buf++ = pat->content.CharRange.ptr_c; | ||||||
|       break; |       break; | ||||||
|     case UPTNumRange: |     case UPTNumRange: | ||||||
|         len = snprintf(buf, buflen, "%0*d", |       len = snprintf(buf, buflen, "%0*ld", | ||||||
|                      pat->content.NumRange.padlength, |                      pat->content.NumRange.padlength, | ||||||
|                      pat->content.NumRange.ptr_n); |                      pat->content.NumRange.ptr_n); | ||||||
|       buf += len; |       buf += len; | ||||||
| @@ -513,7 +520,6 @@ int glob_next_url(char **globbed, URLGlob *glob) | |||||||
|       return CURLE_FAILED_INIT; |       return CURLE_FAILED_INIT; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   } |  | ||||||
|   *buf = '\0'; |   *buf = '\0'; | ||||||
|  |  | ||||||
|   *globbed = strdup(glob->glob_buffer); |   *globbed = strdup(glob->glob_buffer); | ||||||
| @@ -549,34 +555,44 @@ int glob_match_url(char **result, char *filename, URLGlob *glob) | |||||||
|       unsigned long i; |       unsigned long i; | ||||||
|       char *ptr = filename; |       char *ptr = filename; | ||||||
|       unsigned long num = strtoul(&filename[1], &filename, 10); |       unsigned long num = strtoul(&filename[1], &filename, 10); | ||||||
|       i = num - 1UL; |       URLPattern *pat =NULL; | ||||||
|  |  | ||||||
|       if(num && (i <= glob->size / 2)) { |       if(num < glob->size) { | ||||||
|         URLPattern pat = glob->pattern[i]; |         num--; /* make it zero based */ | ||||||
|         switch (pat.type) { |         /* 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: |         case UPTSet: | ||||||
|           if(pat.content.Set.elements) { |           if(pat->content.Set.elements) { | ||||||
|             appendthis = pat.content.Set.elements[pat.content.Set.ptr_s]; |             appendthis = pat->content.Set.elements[pat->content.Set.ptr_s]; | ||||||
|             appendlen = |             appendlen = | ||||||
|               strlen(pat.content.Set.elements[pat.content.Set.ptr_s]); |               strlen(pat->content.Set.elements[pat->content.Set.ptr_s]); | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         case UPTCharRange: |         case UPTCharRange: | ||||||
|           numbuf[0] = pat.content.CharRange.ptr_c; |           numbuf[0] = pat->content.CharRange.ptr_c; | ||||||
|           numbuf[1] = 0; |           numbuf[1] = 0; | ||||||
|           appendthis = numbuf; |           appendthis = numbuf; | ||||||
|           appendlen = 1; |           appendlen = 1; | ||||||
|           break; |           break; | ||||||
|         case UPTNumRange: |         case UPTNumRange: | ||||||
|           snprintf(numbuf, sizeof(numbuf), "%0*d", |           snprintf(numbuf, sizeof(numbuf), "%0*d", | ||||||
|                    pat.content.NumRange.padlength, |                    pat->content.NumRange.padlength, | ||||||
|                    pat.content.NumRange.ptr_n); |                    pat->content.NumRange.ptr_n); | ||||||
|           appendthis = numbuf; |           appendthis = numbuf; | ||||||
|           appendlen = strlen(numbuf); |           appendlen = strlen(numbuf); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           printf("internal error: invalid pattern type (%d)\n", |           fprintf(stderr, "internal error: invalid pattern type (%d)\n", | ||||||
|                  (int)pat.type); |                   (int)pat->type); | ||||||
|           Curl_safefree(target); |           Curl_safefree(target); | ||||||
|           return CURLE_FAILED_INIT; |           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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -31,11 +31,13 @@ typedef enum { | |||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|   URLPatternType type; |   URLPatternType type; | ||||||
|  |   int globindex; /* the number of this particular glob or -1 if not used | ||||||
|  |                     within {} or [] */ | ||||||
|   union { |   union { | ||||||
|     struct { |     struct { | ||||||
|       char **elements; |       char **elements; | ||||||
|       short size; |       int size; | ||||||
|       short ptr_s; |       int ptr_s; | ||||||
|     } Set; |     } Set; | ||||||
|     struct { |     struct { | ||||||
|       char min_c; |       char min_c; | ||||||
| @@ -44,29 +46,29 @@ typedef struct { | |||||||
|       int step; |       int step; | ||||||
|     } CharRange; |     } CharRange; | ||||||
|     struct { |     struct { | ||||||
|       int min_n; |       unsigned long min_n; | ||||||
|       int max_n; |       unsigned long max_n; | ||||||
|       short padlength; |       int padlength; | ||||||
|       int ptr_n; |       unsigned long ptr_n; | ||||||
|       int step; |       unsigned long step; | ||||||
|     } NumRange ; |     } NumRange ; | ||||||
|   } content; |   } content; | ||||||
| } URLPattern; | } URLPattern; | ||||||
|  |  | ||||||
| /* the total number of globs supported */ | /* the total number of globs supported */ | ||||||
| #define GLOB_PATTERN_NUM 9 | #define GLOB_PATTERN_NUM 100 | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|   char *literal[10]; |   URLPattern pattern[GLOB_PATTERN_NUM]; | ||||||
|   URLPattern pattern[GLOB_PATTERN_NUM+1]; |  | ||||||
|   size_t size; |   size_t size; | ||||||
|   size_t urllen; |   size_t urllen; | ||||||
|   char *glob_buffer; |   char *glob_buffer; | ||||||
|   char beenhere; |   char beenhere; | ||||||
|   char errormsg[80]; /* error message buffer */ |   const char *error; /* error message */ | ||||||
|  |   size_t pos;        /* column position of error or 0 */ | ||||||
| } URLGlob; | } URLGlob; | ||||||
|  |  | ||||||
| int glob_url(URLGlob**, char*, int *, FILE *); | int glob_url(URLGlob**, char*, unsigned long *, FILE *); | ||||||
| int glob_next_url(char **, URLGlob *); | int glob_next_url(char **, URLGlob *); | ||||||
| int glob_match_url(char **, char*, URLGlob *); | int glob_match_url(char **, char*, URLGlob *); | ||||||
| void glob_cleanup(URLGlob* glob); | 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 |  * This software is licensed as described in the file COPYING, which | ||||||
|  * you should have received as part of this distribution. The terms |  * you should have received as part of this distribution. The terms | ||||||
| @@ -23,13 +23,18 @@ | |||||||
|  |  | ||||||
| #ifdef HAVE_FSETXATTR | #ifdef HAVE_FSETXATTR | ||||||
| #  include <sys/xattr.h> /* header from libc, not from libattr */ | #  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 | #endif | ||||||
|  |  | ||||||
| #include "tool_xattr.h" | #include "tool_xattr.h" | ||||||
|  |  | ||||||
| #include "memdebug.h" /* keep this as LAST include */ | #include "memdebug.h" /* keep this as LAST include */ | ||||||
|  |  | ||||||
| #ifdef HAVE_FSETXATTR | #ifdef USE_XATTR | ||||||
|  |  | ||||||
| /* mapping table of curl metadata to extended attribute names */ | /* mapping table of curl metadata to extended attribute names */ | ||||||
| static const struct xattr_mapping { | 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); |       err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0); | ||||||
| #elif defined(HAVE_FSETXATTR_5) | #elif defined(HAVE_FSETXATTR_5) | ||||||
|       err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0); |       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 | #endif | ||||||
|     } |     } | ||||||
|     i++; |     i++; | ||||||
|   | |||||||
| @@ -125,6 +125,13 @@ SLOWDOWN | |||||||
|  - Send FTP responses with 0.01 sec delay between each byte |  - Send FTP responses with 0.01 sec delay between each byte | ||||||
| PASVBADIP | PASVBADIP | ||||||
|  - makes PASV send back an illegal IP in its 227 response |  - 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: | For HTTP/HTTPS: | ||||||
| auth_required   if this is set and a POST/PUT is made without auth, the | 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 | connection-monitor When used, this will log [DISCONNECT] to the server.input | ||||||
|                log when the connection is disconnected. |                log when the connection is disconnected. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | For TFTP: | ||||||
|  | writedelay: [secs] delay this amount between reply packets (each packet being | ||||||
|  |                    512 bytes payload) | ||||||
| </servercmd> | </servercmd> | ||||||
| </reply> | </reply> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -64,12 +64,14 @@ test700 test701 test702 test703 test704 test705 test706 test707 test708 \ | |||||||
| test709 test710 test711 test712 \ | test709 test710 test711 test712 \ | ||||||
| \ | \ | ||||||
| test800 test801 test802 test803 test804 test805 test806 test807 test808 \ | 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 \ | 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 \ | test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \ | ||||||
| test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \ | 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 \ | test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \ | ||||||
| test1216 test1217 test1218 test1219 \ | test1216 test1217 test1218 test1219 \ | ||||||
| test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \ | 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 \ | test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \ | ||||||
| test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \ | test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \ | ||||||
| @@ -110,7 +113,7 @@ test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1395 \ | |||||||
| test1396 \ | test1396 \ | ||||||
| \ | \ | ||||||
| test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ | 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 \ | test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ | ||||||
| test1508 test1509 test1510 test1511 test1512 \ | test1508 test1509 test1510 test1511 test1512 \ | ||||||
|   | |||||||
| @@ -89,7 +89,7 @@ ftps | |||||||
| FTPS download with strict timeout and slow data transfer | FTPS download with strict timeout and slow data transfer | ||||||
|  </name> |  </name> | ||||||
|  <command timeout="1"> |  <command timeout="1"> | ||||||
| -k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 7 | -k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 16 | ||||||
| </command> | </command> | ||||||
| </client> | </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 | body | ||||||
| </stdin> | </stdin> | ||||||
|  <command> |  <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> | </command> | ||||||
| </client> | </client> | ||||||
|  |  | ||||||
| @@ -46,10 +46,9 @@ smtp://smtp.1320:%SMTPPORT/user --mail-rcpt 1320@foo --mail-rcpt 1320@foobar.exa | |||||||
| ^User-Agent: curl/.* | ^User-Agent: curl/.* | ||||||
| </strip> | </strip> | ||||||
| <protocol> | <protocol> | ||||||
| EHLO user | EHLO 1320 | ||||||
| MAIL FROM:<1320@from> | MAIL FROM:<sender@example.com> | ||||||
| RCPT TO:<1320@foo> | RCPT TO:<recipient@example.com> | ||||||
| RCPT TO:<1320@foobar.example> |  | ||||||
| DATA | DATA | ||||||
| QUIT | QUIT | ||||||
| </protocol> | </protocol> | ||||||
|   | |||||||
| @@ -11,6 +11,9 @@ SMTP | |||||||
| # | # | ||||||
| # Server-side | # Server-side | ||||||
| <reply> | <reply> | ||||||
|  | <servercmd> | ||||||
|  | CAPA SIZE | ||||||
|  | </servercmd> | ||||||
| </reply> | </reply> | ||||||
|  |  | ||||||
| # | # | ||||||
| @@ -29,7 +32,7 @@ To: another | |||||||
| body | body | ||||||
| </file> | </file> | ||||||
|  <command> |  <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> | </command> | ||||||
| </client> | </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 data after the test has been "shot" | ||||||
| <verify> | <verify> | ||||||
| <protocol> | <protocol> | ||||||
| EHLO user | EHLO 1406 | ||||||
| MAIL FROM:<1406@from> SIZE=38 | MAIL FROM:<sender@example.com> SIZE=38 | ||||||
| RCPT TO:<1406@foo> | RCPT TO:<recipient.one@example.com> | ||||||
| RCPT TO:<1406@foobar.example> | RCPT TO:<recipient.two@example.com> | ||||||
| DATA | DATA | ||||||
| QUIT | QUIT | ||||||
| </protocol> | </protocol> | ||||||
| @@ -65,19 +68,19 @@ int main(int argc, char *argv[]) | |||||||
|   struct curl_slist *slist1; |   struct curl_slist *slist1; | ||||||
|  |  | ||||||
|   slist1 = NULL; |   slist1 = NULL; | ||||||
|   slist1 = curl_slist_append(slist1, "1406@foo"); |   slist1 = curl_slist_append(slist1, "recipient.one@example.com"); | ||||||
|   slist1 = curl_slist_append(slist1, "1406@foobar.example"); |   slist1 = curl_slist_append(slist1, "recipient.two@example.com"); | ||||||
|  |  | ||||||
|   hnd = curl_easy_init(); |   hnd = curl_easy_init(); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)38); |   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_HEADER, 1L); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); |   curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); |   curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); |   curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); |   curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||||||
|   curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 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); |   curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1); | ||||||
|  |  | ||||||
|   /* Here is a list of options the curl code used that cannot get generated |   /* 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 | body | ||||||
| </stdin> | </stdin> | ||||||
|  <command> |  <command> | ||||||
| smtp://%HOSTIP:%SMTPPORT/user | smtp://%HOSTIP:%SMTPPORT/1507 | ||||||
| </command> | </command> | ||||||
| </client> | </client> | ||||||
|  |  | ||||||
| @@ -40,7 +40,7 @@ smtp://%HOSTIP:%SMTPPORT/user | |||||||
| # Verify data after the test has been "shot" | # Verify data after the test has been "shot" | ||||||
| <verify> | <verify> | ||||||
| <protocol> | <protocol> | ||||||
| EHLO user | EHLO 1507 | ||||||
| MAIL FROM:<1507-realuser@example.com> | MAIL FROM:<1507-realuser@example.com> | ||||||
| RCPT TO:<1507-recipient@example.com> | RCPT TO:<1507-recipient@example.com> | ||||||
| DATA | DATA | ||||||
|   | |||||||
| @@ -123,22 +123,22 @@ chkhostname curlhost | |||||||
| <protocol> | <protocol> | ||||||
| GET /20320100 HTTP/1.1 | GET /20320100 HTTP/1.1 | ||||||
| Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320100 HTTP/1.1 | GET /20320100 HTTP/1.1 | ||||||
| Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320200 HTTP/1.1 | GET /20320200 HTTP/1.1 | ||||||
| Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= | Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320200 HTTP/1.1 | GET /20320200 HTTP/1.1 | ||||||
| Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q= | Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| </protocol> | </protocol> | ||||||
|   | |||||||
| @@ -124,22 +124,22 @@ chkhostname curlhost | |||||||
| <protocol> | <protocol> | ||||||
| GET /20320100 HTTP/1.1 | GET /20320100 HTTP/1.1 | ||||||
| Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320100 HTTP/1.1 | GET /20320100 HTTP/1.1 | ||||||
| Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320200 HTTP/1.1 | GET /20320200 HTTP/1.1 | ||||||
| Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= | Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| GET /20320200 HTTP/1.1 | GET /20320200 HTTP/1.1 | ||||||
| Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q= | Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q= | ||||||
| Host: 127.0.0.1:8990 | Host: 127.0.0.1:%HTTPPORT | ||||||
| Accept: */* | Accept: */* | ||||||
|  |  | ||||||
| </protocol> | </protocol> | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user