Compare commits
	
		
			335 Commits
		
	
	
		
			curl-7_17_
			...
			curl-7_18_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | a7b98f5f6b | ||
|   | 6bae091c1b | ||
|   | 33d68653f0 | ||
|   | 267836e83c | ||
|   | 87fdfe770d | ||
|   | 8fca5c2e69 | ||
|   | 5f2055729e | ||
|   | c6df788866 | ||
|   | e67b2524d1 | ||
|   | d7bcc26179 | ||
|   | 69e540dfa6 | ||
|   | 2198869eb1 | ||
|   | fb07259e0d | ||
|   | 9d28a0252c | ||
|   | d54c14ccf9 | ||
|   | 41def4be6e | ||
|   | 2d38d0d515 | ||
|   | e796c79d18 | ||
|   | c93ba48da2 | ||
|   | e322513698 | ||
|   | 6fa72e6417 | ||
|   | c914e6ea5d | ||
|   | 79cb74f03a | ||
|   | 34cf35051a | ||
|   | 9bd28a021f | ||
|   | 5ee3f41e0d | ||
|   | 64e88ff6a7 | ||
|   | acd7c94598 | ||
|   | bdb2beb8e4 | ||
|   | 727e23322f | ||
|   | ef0ed9b720 | ||
|   | a674654f83 | ||
|   | 3caeb0a91f | ||
|   | a4eddf0d0d | ||
|   | fcf9029179 | ||
|   | e40327ba00 | ||
|   | bdd0e3d3f5 | ||
|   | e9490fdbd9 | ||
|   | bd40b3ff3f | ||
|   | 8c66811e09 | ||
|   | daadcfd1de | ||
|   | 62df0ff025 | ||
|   | 01d95b56a0 | ||
|   | f6adae8d35 | ||
|   | bcaadb4284 | ||
|   | 8d963aa0e2 | ||
|   | 0530b0a5ca | ||
|   | 5396121595 | ||
|   | bcfc7d90d1 | ||
|   | 47246eb401 | ||
|   | 3620e71010 | ||
|   | c522f349fe | ||
|   | 6893fcaa9b | ||
|   | 301ae1ae1b | ||
|   | ddaa78f08b | ||
|   | 3d55877764 | ||
|   | 3ee32d7920 | ||
|   | b3de497d83 | ||
|   | ed6466d176 | ||
|   | 991505e077 | ||
|   | 56f17d2c9f | ||
|   | 19ae96f4d0 | ||
|   | 53108806af | ||
|   | 1d620a3df4 | ||
|   | 69f685056d | ||
|   | 9c7d4394f9 | ||
|   | bcc3c9279a | ||
|   | 5d63404966 | ||
|   | a8ae8087c4 | ||
|   | 502da27d65 | ||
|   | 4ab8ebb232 | ||
|   | f866af912d | ||
|   | 4f00a8db73 | ||
|   | 5004529685 | ||
|   | 2b63eb8511 | ||
|   | f09fe4b49f | ||
|   | 22c76df44d | ||
|   | 35be09cf58 | ||
|   | 3564aec388 | ||
|   | a042090467 | ||
|   | 148d727525 | ||
|   | 08adf67969 | ||
|   | e2c817731a | ||
|   | 8df7e0bdba | ||
|   | 14ff7e75e0 | ||
|   | d270d6518a | ||
|   | 18faa50940 | ||
|   | 0ce484eed9 | ||
|   | bce5ae9a07 | ||
|   | 15f832d1c2 | ||
|   | c249a8aa1b | ||
|   | fc794ae012 | ||
|   | 07227e8089 | ||
|   | 32cc75d6cb | ||
|   | 1c0a19ad53 | ||
|   | de23b98522 | ||
|   | 5e1c9e90d9 | ||
|   | 59b4bdf78d | ||
|   | 34d02d1969 | ||
|   | 2408b236ca | ||
|   | 4acd437952 | ||
|   | 314f62958d | ||
|   | c616d56e96 | ||
|   | f111c9edae | ||
|   | 7138296633 | ||
|   | 195e94c0fa | ||
|   | cadd08f36a | ||
|   | 7306b7829b | ||
|   | 423309541a | ||
|   | 9c6533d287 | ||
|   | b430576436 | ||
|   | 65008a4e55 | ||
|   | 3df484088f | ||
|   | 2912189875 | ||
|   | fcb2595ed6 | ||
|   | 0878af3ec0 | ||
|   | fe0d7aee49 | ||
|   | 2e42b0a252 | ||
|   | fcc485092a | ||
|   | a4945fe687 | ||
|   | 88d89b2177 | ||
|   | 61a2d5ea75 | ||
|   | c479c64333 | ||
|   | 7a2177dc42 | ||
|   | bf6e2f28ba | ||
|   | f5da1e5484 | ||
|   | fd8d862c37 | ||
|   | 083d3190e5 | ||
|   | 6787d1ed35 | ||
|   | d9023c16ab | ||
|   | 193d33fd4a | ||
|   | a46b40b7fd | ||
|   | 0b9b8acb08 | ||
|   | bf98b635cd | ||
|   | 7795eb6db8 | ||
|   | 31674559d3 | ||
|   | 04e4d9a0b3 | ||
|   | f277124a0f | ||
|   | 6adf5880f5 | ||
|   | 4e8c4fc80b | ||
|   | fc1d1ea934 | ||
|   | 9cd30c2012 | ||
|   | d639ed1aaf | ||
|   | c3a02f5407 | ||
|   | 674845f239 | ||
|   | 07a1857d59 | ||
|   | f4ffa85f60 | ||
|   | bcd7d03b3b | ||
|   | 82c9379b6c | ||
|   | c1730dc50a | ||
|   | 20695098c8 | ||
|   | ee52ae001c | ||
|   | 26115aac5d | ||
|   | ca6b27aed2 | ||
|   | 4fabe22173 | ||
|   | 7b1a22147e | ||
|   | dc24540ed1 | ||
|   | 92eae30f4d | ||
|   | 79ef08f631 | ||
|   | e3c5f8374b | ||
|   | 6dc68b4193 | ||
|   | afab4d888f | ||
|   | c751dfd65d | ||
|   | dbca1347f1 | ||
|   | 3b6315ce1f | ||
|   | 3c1db5f250 | ||
|   | 562e9b7bf3 | ||
|   | a83e72692f | ||
|   | bd99a7dc8c | ||
|   | db2d52a792 | ||
|   | 24602edc17 | ||
|   | b0b40d9a00 | ||
|   | 71b105ceb1 | ||
|   | ccb4956145 | ||
|   | 3d09cb0a88 | ||
|   | a03c2d825b | ||
|   | 06fb242e23 | ||
|   | a086952244 | ||
|   | 2b314064ae | ||
|   | 439990be88 | ||
|   | 41d8186c7e | ||
|   | 6e9276229f | ||
|   | 636f5eb882 | ||
|   | 963ef5414c | ||
|   | 975812d246 | ||
|   | 089668ec73 | ||
|   | cc0ce38acc | ||
|   | 8cdff55b80 | ||
|   | 662bee7193 | ||
|   | f8172f85b1 | ||
|   | 7d3ea12b62 | ||
|   | 59dc9085d1 | ||
|   | 4e4f33a297 | ||
|   | 8fa599215b | ||
|   | 31e2409d6b | ||
|   | 15c304225f | ||
|   | e1998e3b58 | ||
|   | 5c447f2499 | ||
|   | 9d0ffb9cc6 | ||
|   | 2be50baf97 | ||
|   | a1772ca406 | ||
|   | 30eda92a53 | ||
|   | 1f058f1014 | ||
|   | 84d0477cb9 | ||
|   | 1c93e75375 | ||
|   | 380ed8bebf | ||
|   | 98e8978857 | ||
|   | 56ddfbea6e | ||
|   | 45a2240ead | ||
|   | f75ba55b51 | ||
|   | 46e6115d72 | ||
|   | 800a72878a | ||
|   | 649f7b7fd3 | ||
|   | c1b734a3e1 | ||
|   | cf806748ec | ||
|   | b28dc011e0 | ||
|   | ee4fef3768 | ||
|   | 058a023fae | ||
|   | 0c367fef94 | ||
|   | a418d290f1 | ||
|   | 08cb30801c | ||
|   | 788de4f7ba | ||
|   | ebce0a16f6 | ||
|   | df546bd58c | ||
|   | 05221e9056 | ||
|   | e963714de6 | ||
|   | dc11239ff1 | ||
|   | d59841618d | ||
|   | 8d3964782a | ||
|   | 162c039e9d | ||
|   | 13648f8ccd | ||
|   | 5b809a3104 | ||
|   | 3daa54d636 | ||
|   | 8f1829d1d2 | ||
|   | 6efb6addf2 | ||
|   | d789097af0 | ||
|   | 4bd2d49ca1 | ||
|   | ecfede9b3c | ||
|   | cb04619de2 | ||
|   | 61e2e86aef | ||
|   | 9b86eecb94 | ||
|   | 35212da048 | ||
|   | 755e743cdd | ||
|   | 1a323390ec | ||
|   | 23559fd118 | ||
|   | d994a873a4 | ||
|   | b6575ce0b0 | ||
|   | e2b2a84497 | ||
|   | 86956c2261 | ||
|   | ef6dfdc7fd | ||
|   | f3b85ef79d | ||
|   | 1d7e42ee9f | ||
|   | 6dfb5b4e1f | ||
|   | 930085751c | ||
|   | 258c4686b2 | ||
|   | 600d0b1303 | ||
|   | 2f928797cf | ||
|   | f3f06e823c | ||
|   | 58292f49c5 | ||
|   | 5376d1047c | ||
|   | 1746b57161 | ||
|   | 0561bffab3 | ||
|   | 968e943eac | ||
|   | 5be00c95a7 | ||
|   | c80b9c3778 | ||
|   | 536f98a766 | ||
|   | c4e5613a7d | ||
|   | bff962398d | ||
|   | 2b15823dab | ||
|   | 59dcc7e191 | ||
|   | ea3fe98867 | ||
|   | 4f05613fbb | ||
|   | 22e52ddd6e | ||
|   | 1125d45397 | ||
|   | 44d408204a | ||
|   | 50feea3eef | ||
|   | ca95f58ac0 | ||
|   | ed636cbe44 | ||
|   | 738e4f410c | ||
|   | 4e731a0189 | ||
|   | 5cf6a539fe | ||
|   | 17fde12fb8 | ||
|   | 5c8b973d4f | ||
|   | b22e03b2b2 | ||
|   | a2926ebe7c | ||
|   | c508d70258 | ||
|   | f5971f54ff | ||
|   | c5b16d4468 | ||
|   | 3c71a1bab7 | ||
|   | 3ec322685b | ||
|   | 9a39839a43 | ||
|   | e87c996fe0 | ||
|   | 32195c673d | ||
|   | b99a61c5b0 | ||
|   | c960cd41e8 | ||
|   | a29471d0f7 | ||
|   | ba6f20a244 | ||
|   | 61572a1f97 | ||
|   | dee3844f13 | ||
|   | cbd1a77ec2 | ||
|   | 33f7ac06c3 | ||
|   | 70f10f1ac9 | ||
|   | 775b60fa09 | ||
|   | 66e4d391d3 | ||
|   | caf880be18 | ||
|   | c8355c27e9 | ||
|   | c2d7e2ae17 | ||
|   | 98ecad0da6 | ||
|   | bbc4e05434 | ||
|   | ad6e28073c | ||
|   | af29dcbafb | ||
|   | b9a7f4e502 | ||
|   | 51009a40b4 | ||
|   | 2ec8f77f21 | ||
|   | 7f62028d66 | ||
|   | d34fe06fb0 | ||
|   | 2f3d520571 | ||
|   | 48dd0c5673 | ||
|   | 8be493296d | ||
|   | 6f33531861 | ||
|   | 16897354bc | ||
|   | 823a0454a6 | ||
|   | 6790c559af | ||
|   | c56c4a0a47 | ||
|   | 45064c5778 | ||
|   | 7aba59f577 | ||
|   | 59b05ac383 | ||
|   | 9b15f1be26 | ||
|   | 38cd2d781f | ||
|   | 2f285b3f16 | ||
|   | 57d2fb41d0 | ||
|   | 0f77fe55b6 | ||
|   | 68ee002ad0 | ||
|   | 1fc3b18592 | ||
|   | 5a5287ef2a | 
							
								
								
									
										430
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										430
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -6,6 +6,436 @@ | |||||||
|  |  | ||||||
|                                   Changelog |                                   Changelog | ||||||
|  |  | ||||||
|  | Version 7.18.0 (28 January 2008) | ||||||
|  |  | ||||||
|  | Daniel S (27 Jan 2008) | ||||||
|  | - Dmitry Kurochkin: In "real world" testing I found more bugs in | ||||||
|  |   pipelining. Broken connection is not restored and we get into infinite | ||||||
|  |   loop. It happens because of wrong is_in_pipeline values. | ||||||
|  |  | ||||||
|  | Daniel S (26 Jan 2008) | ||||||
|  | - Kevin Reed filed bug report #1879375 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1879375) which describes how libcurl | ||||||
|  |   got lost in this scenario: proxy tunnel (or HTTPS over proxy), ask to do any | ||||||
|  |   proxy authentication and the proxy replies with an auth (like NTLM) and then | ||||||
|  |   closes the connection after that initial informational response. | ||||||
|  |  | ||||||
|  |   libcurl would not properly re-initialize the connection to the proxy and | ||||||
|  |   continue the auth negotiation like supposed. It does now however, as it will | ||||||
|  |   now detect if one or more authentication methods were available and asked | ||||||
|  |   for, and will thus retry the connection and continue from there. | ||||||
|  |  | ||||||
|  | - I made the progress callback get called properly during proxy CONNECT. | ||||||
|  |  | ||||||
|  | Daniel S (23 Jan 2008) | ||||||
|  | - Igor Franchuk pointed out that CURLOPT_COOKIELIST set to "ALL" leaked | ||||||
|  |   memory, and so did "SESS". Fixed now. | ||||||
|  |  | ||||||
|  | Yang Tse (22 Jan 2008) | ||||||
|  | - Check poll.h at configuration time, and use it when sys/poll.h unavailable | ||||||
|  |  | ||||||
|  | Daniel S (22 Jan 2008) | ||||||
|  | - Dmitry Kurochkin removed the cancelled state for pipelining, as we agreed | ||||||
|  |   that it is bad anyway. Starting now, removing a handle that is in used in a | ||||||
|  |   pipeline will break the pipeline - it'll be set back up again but still... | ||||||
|  |  | ||||||
|  | Yang Tse (21 Jan 2008) | ||||||
|  | - Disable ldap support for cygwin builds, since it breaks whole build process. | ||||||
|  |   Fixing it will affect other platforms, so it is postponed for another release. | ||||||
|  |  | ||||||
|  | Daniel S (18 Jan 2008) | ||||||
|  | - Lau Hang Kin found and fixed a problem with the multi interface when doing | ||||||
|  |   CONNECT over a proxy. curl_multi_fdset() didn't report back the socket | ||||||
|  |   properly during that state, due to a missing case in the switch in the | ||||||
|  |   multi_getsock() function. | ||||||
|  |  | ||||||
|  | Yang Tse (17 Jan 2008) | ||||||
|  | - Don't abort tests 518 and 537 when unable to raise the open-file soft limit. | ||||||
|  |  | ||||||
|  | Daniel S (16 Jan 2008) | ||||||
|  | - Nathan Coulter's patch that makes runtests.pl respect the PATH when figuring | ||||||
|  |   out what valgrind to run. | ||||||
|  |  | ||||||
|  | Yang Tse (16 Jan 2008) | ||||||
|  | - Improved handling of out of memory in the command line tool that afected | ||||||
|  |   data url encoded HTTP POSTs when reading it from a file. | ||||||
|  |  | ||||||
|  | Daniel S (16 Jan 2008) | ||||||
|  | - Dmitry Kurochkin worked a lot on improving the HTTP Pipelining support that | ||||||
|  |   previously had a number of flaws, perhaps most notably when an application | ||||||
|  |   fired up N transfers at once as then they wouldn't pipeline at all that | ||||||
|  |   nicely as anyone would think... Test case 530 was also updated to take the | ||||||
|  |   improved functionality into account. | ||||||
|  |  | ||||||
|  | - Calls to Curl_failf() are not supposed to provide a trailing newline as the | ||||||
|  |   function itself adds that. Fixed on 50 or something strings! | ||||||
|  |  | ||||||
|  | Daniel S (15 Jan 2008) | ||||||
|  | - I made the torture test on test 530 go through. This was actually due to | ||||||
|  |   silly code left from when we switched to let the multi handle "hold" the dns | ||||||
|  |   cache when using the multi interface... Of course this only triggered when a | ||||||
|  |   certain function call returned error at the correct moment. | ||||||
|  |  | ||||||
|  | Daniel S (14 Jan 2008) | ||||||
|  | - Joe Malicki filed bug report #1871269 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1871269) and we could fix his hang- | ||||||
|  |   problem that occurred when doing a large HTTP POST request with the | ||||||
|  |   response-body read from a callback. | ||||||
|  |  | ||||||
|  | Daniel S (12 Jan 2008) | ||||||
|  | - I re-arranged the curl --help output. All the options are now sorted on | ||||||
|  |   their long option names and all descriptions are one-liners. | ||||||
|  |  | ||||||
|  | - Eric Landes provided the patch (edited by me) that introduces the | ||||||
|  |   --keepalive-time to curl to set the keepalive probe interval. I also took | ||||||
|  |   the opportunity to rename the recently added no-keep-alive option to | ||||||
|  |   no-keepalive to keep a consistent naming and to avoid getting two dashes in | ||||||
|  |   these option names. Eric also provided an update to the man page for the new | ||||||
|  |   option. | ||||||
|  |  | ||||||
|  | Daniel S (11 Jan 2008) | ||||||
|  | - Daniel Egger made CURLOPT_RANGE work on file:// URLs the very same way it | ||||||
|  |   already worked for FTP:// URLs. | ||||||
|  |  | ||||||
|  | - I made the curl tool switch from using CURLOPT_IOCTLFUNCTION to now use the | ||||||
|  |   spanking new CURLOPT_SEEKFUNCTION simply to take advantage of the improved | ||||||
|  |   performance for the upload resume cases where you want to upload the last | ||||||
|  |   few bytes of a very large file. To implement this decently, I had to switch | ||||||
|  |   the client code for uploading from fopen()/fread() to plain open()/read() so | ||||||
|  |   that we can use lseek() to do >32bit seeks (as fseek() doesn't allow that) | ||||||
|  |   on systems that offer support for that. | ||||||
|  |  | ||||||
|  | Daniel S (10 Jan 2008) | ||||||
|  | - Michal Marek made curl-config --libs not include /usr/lib64 in the output | ||||||
|  |   (it already before skipped /usr/lib).  /usr/lib64 is the default library | ||||||
|  |   directory on many 64bit systems and it's unlikely that anyone would use the | ||||||
|  |   path privately on systems where it's not. | ||||||
|  |  | ||||||
|  | - Georg Lippitsch brought CURLOPT_SEEKFUNCTION and CURLOPT_SEEKDATA to allow | ||||||
|  |   libcurl to seek in a given input stream. This is particularly important when | ||||||
|  |   doing upload resumes when there's already a huge part of the file present | ||||||
|  |   remotely. Before, and still if this callback isn't used, libcurl will read | ||||||
|  |   and through away the entire file up to the point to where the resuming | ||||||
|  |   begins (which of course can be a slow opereration depending on file size, | ||||||
|  |   I/O bandwidth and more). This new function will also be preferred to get | ||||||
|  |   used instead of the CURLOPT_IOCTLFUNCTION for seeking back in a stream when | ||||||
|  |   doing multi-stage HTTP auth with POST/PUT. | ||||||
|  |  | ||||||
|  | - Nikitinskit Dmitriy filed bug report #1868255 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1868255) with a patch. It identifies | ||||||
|  |   and fixes a problem with parsing WWW-Authenticate: headers with additional | ||||||
|  |   spaces in the line that the parser wasn't written to deal with. | ||||||
|  |  | ||||||
|  | Daniel S (8 Jan 2008) | ||||||
|  | - Introducing curl_easy_pause() and new magic return codes for both the read | ||||||
|  |   and the write callbacks that now can make a connection's reading and/or | ||||||
|  |   writing get paused. | ||||||
|  |  | ||||||
|  | Daniel S (6 Jan 2008) | ||||||
|  | - Jeff Johnson filed bug report #1863171 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1863171) where he pointed out that | ||||||
|  |   libcurl's date parser didn't accept a +1300 time zone which actually is used | ||||||
|  |   fairly often (like New Zealand's Dailight Savings Time), so I modified the | ||||||
|  |   parser to now accept up to and including -1400 to +1400. | ||||||
|  |  | ||||||
|  | Daniel S (5 Jan 2008) | ||||||
|  | - Based on further discussion on curl-library, I reverted yesterday's SOCKS5 | ||||||
|  |   code to instead introduce support for a new proxy type called | ||||||
|  |   CURLPROXY_SOCKS5_HOSTNAME that is used to send the host name to the proxy | ||||||
|  |   instead of IP address and there's thus no longer any need for a new | ||||||
|  |   curl_easy_setopt() option. | ||||||
|  |  | ||||||
|  |   The default SOCKS5 proxy is again back to sending the IP address to the | ||||||
|  |   proxy.  The new curl command line option for enabling sending host name to a | ||||||
|  |   SOCKS5 proxy is now --socks5-hostname. | ||||||
|  |  | ||||||
|  | Daniel S (4 Jan 2008) | ||||||
|  | - Based on Maxim Perenesenko's patch, we now do SOCKS5 operations and let the | ||||||
|  |   proxy do the host name resolving and only if --socks5ip (or | ||||||
|  |   CURLOPT_SOCKS5_RESOLVE_LOCAL) is used we resolve the host name locally and | ||||||
|  |   pass on the IP address only to the proxy. | ||||||
|  |  | ||||||
|  | Yang Tse (3 Jan 2008) | ||||||
|  | - Modified test harness to allow SCP, SFTP and SOCKS4 tests to run with | ||||||
|  |   OpenSSH 2.9.9, SunSSH 1.0 or later versions. SOCKS5 tests need OpenSSH | ||||||
|  |   3.7, SunSSH 1.0 or later. | ||||||
|  |  | ||||||
|  | Daniel S (2 Jan 2008) | ||||||
|  | - I fixed two cases of missing return code checks when handling chunked | ||||||
|  |   decoding where a write error (or abort return from a callback) didn't stop | ||||||
|  |   libcurl's processing. | ||||||
|  |  | ||||||
|  | - I removed the socklen_t use from the public curl/curl.h header and instead | ||||||
|  |   made it an unsigned int. The type was only used in the curl_sockaddr struct | ||||||
|  |   definition (only used by the curl_opensocket_callback). On all platforms I | ||||||
|  |   could find information about, socklen_t is 32 unsigned bits large so I don't | ||||||
|  |   think this will break the API or ABI. The main reason for this change is of | ||||||
|  |   course for all the platforms that don't have a socklen_t definition in their | ||||||
|  |   headers to build fine again. Providing our own configure magic and custom | ||||||
|  |   definition of socklen_t on those systems proved to work but was a lot of | ||||||
|  |   cruft, code and extra magic needed - when this very small change of type | ||||||
|  |   seems harmless and still solves the missing socklen_t problem. | ||||||
|  |  | ||||||
|  | - Richard Atterer brought a patch that added support for SOCKS4a proxies, | ||||||
|  |   which is an inofficial PROXY4 variant that sends the hostname to the proxy | ||||||
|  |   instead of the resolved address (which is already supported by SOCKS5). | ||||||
|  |   --socks4a is the curl command line option for it and CURLOPT_PROXYTYPE can | ||||||
|  |   now be set to CURLPROXY_SOCKS4A as well. | ||||||
|  |  | ||||||
|  | Daniel S (1 Jan 2008) | ||||||
|  | - Mohun Biswas pointed out that --libcurl generated a source code with an int | ||||||
|  |   function but without a return statement. While fixing that, I also took care | ||||||
|  |   about adding some better comments for the generated code. | ||||||
|  |  | ||||||
|  | Daniel S (27 Dec 2007) | ||||||
|  | - Dmitry Kurochkin mentioned a flaw | ||||||
|  |   (http://curl.haxx.se/mail/lib-2007-12/0252.html) in detect_proxy() which | ||||||
|  |   failed to set the bits.proxy variable properly when an environment variable | ||||||
|  |   told libcurl to use a http proxy. | ||||||
|  |  | ||||||
|  | Daniel S (26 Dec 2007) | ||||||
|  | - In an attempt to repeat the problem in bug report #1850730 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1850730) I wrote up test case 552. The | ||||||
|  |   test is doing a 70K POST with a read callback and an ioctl callback over a | ||||||
|  |   proxy requiring Digest auth. The test case code is more or less identical to | ||||||
|  |   the test recipe code provided by Spacen Jasset (who submitted the bug | ||||||
|  |   report). | ||||||
|  |  | ||||||
|  | Daniel S (25 Dec 2007) | ||||||
|  | - Gary Maxwell filed bug report #1856628 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1856628) and provided a fix for the | ||||||
|  |   (small) memory leak in the SSL session ID caching code. It happened when a | ||||||
|  |   previous entry in the cache was re-used. | ||||||
|  |  | ||||||
|  | Daniel Fandrich (19 Dec 2007) | ||||||
|  | - Ensure that nroff doesn't put anything but ASCII characters into the | ||||||
|  |   --manual text. | ||||||
|  |  | ||||||
|  | Yang Tse (18 Dec 2007) | ||||||
|  | - MSVC 9.0 (VS2008) does not support Windows build targets prior to WinXP, | ||||||
|  |   and makes wrong asumptions of build target when it isn't specified. So, | ||||||
|  |   if no build target has been defined we will target WinXP when building | ||||||
|  |   curl/libcurl with MSVC 9.0 (VS2008). | ||||||
|  |  | ||||||
|  | - (http://curl.haxx.se/mail/archive-2007-12/0039.html) reported and fixed | ||||||
|  |   a file truncation problem on Windows build targets triggered when retrying | ||||||
|  |   a download with curl. | ||||||
|  |  | ||||||
|  | Daniel S (17 Dec 2007) | ||||||
|  | - Mateusz Loskot pointed out that MSVC 9.0 (VS2008) has the pollfd struct and | ||||||
|  |   defines in winsock2.h somehow differently than previous versions and that | ||||||
|  |   curl 7.17.1 would fail to compile out of the box. | ||||||
|  |  | ||||||
|  | Daniel S (13 Dec 2007) | ||||||
|  | - David Wright filed bug report #1849764 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1849764) with an included fix. He | ||||||
|  |   identified a problem for re-used connections that previously had sent | ||||||
|  |   Expect: 100-continue and in some situations the subsequent POST (that didn't | ||||||
|  |   use Expect:) still had the internal flag set for its use. David's fix (that | ||||||
|  |   makes the setting of the flag in every single request unconditionally) is | ||||||
|  |   fine and is now used! | ||||||
|  |  | ||||||
|  | Daniel S (12 Dec 2007) | ||||||
|  | - Gilles Blanc made the curl tool enable SO_KEEPALIVE for the connections and | ||||||
|  |   added the --no-keep-alive option that can disable that on demand. | ||||||
|  |  | ||||||
|  | Daniel S (9 Dec 2007) | ||||||
|  | - Andrew Moise filed bug report #1847501 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1847501) and pointed out a memcpy() | ||||||
|  |   that should be memmove() in the convert_lineends() function. | ||||||
|  |  | ||||||
|  | Daniel S (8 Dec 2007) | ||||||
|  | - Renamed all internal static functions that had Curl_ prefixes to no longer | ||||||
|  |   have them. The Curl_ prefix is exclusively used for library internal global | ||||||
|  |   symbols. Static functions can be named anything, except for using Curl_ or | ||||||
|  |   curl_ prefixes. This is for consistency and for easier maintainance and | ||||||
|  |   overview. | ||||||
|  |  | ||||||
|  | - Cleaned up and reformatted the TODO document to look like the FAQ and | ||||||
|  |   CONTRIBUTE, which makes nicer web pages | ||||||
|  |  | ||||||
|  | - Added test cases 549 and 550 that test CURLOPT_PROXY_TRANSFER_MODE. | ||||||
|  |  | ||||||
|  | - Added keywords on a bunch of test cases | ||||||
|  |  | ||||||
|  | - Fixed an OOM problem in the curl code that would lead to fclose on a bad | ||||||
|  |   handle and crash | ||||||
|  |  | ||||||
|  | Daniel S (5 Dec 2007) | ||||||
|  | - Spacen Jasset reported a problem with doing POST (with data read with a | ||||||
|  |   callback) over a proxy when NTLM is used as auth with the proxy. The bug | ||||||
|  |   also concerned Digest and was limited to using callback only. Spacen worked | ||||||
|  |   with us to provide a useful patch. I added the test case 547 and 548 to | ||||||
|  |   verify two variations of POST over proxy with NTLM. | ||||||
|  |  | ||||||
|  | Daniel S (3 Dec 2007) | ||||||
|  | - Ray Pekowski filed bug report #1842029 | ||||||
|  |   (http://curl.haxx.se/bug/view.cgi?id=1842029) in which he identified a | ||||||
|  |   problem with SSL session caching that prevent it from working, and provided | ||||||
|  |   the associated fix! | ||||||
|  |  | ||||||
|  | - Now libcurl (built with OpenSSL) doesn't return error anymore if the remote | ||||||
|  |   SSL-based server doesn't present a certificate when the request is told to | ||||||
|  |   ignore certificate verification anyway. | ||||||
|  |  | ||||||
|  | - Michal Marek introduced CURLOPT_PROXY_TRANSFER_MODE which is used to control | ||||||
|  |   the appending of the "type=" thing on FTP URLs when they are passed to a | ||||||
|  |   HTTP proxy. Some proxies just don't like that appending (which is done | ||||||
|  |   unconditionally in 7.17.1), and some proxies treat binary/ascii transfers | ||||||
|  |   better with the appending done! | ||||||
|  |  | ||||||
|  | Daniel S (29 Nov 2007) | ||||||
|  | - A bug report on the curl-library list showed a HTTP Digest session going on | ||||||
|  |   with a 700+ letter nonce. Previously libcurl only support 127 letter ones | ||||||
|  |   and now I bumped it to 1023. | ||||||
|  |  | ||||||
|  | - Fixed the resumed FTP upload loop to not require that the read callback | ||||||
|  |   returns a full buffer on each invoke. | ||||||
|  |  | ||||||
|  | Daniel S (25 Nov 2007) | ||||||
|  | - Added test case 1015 that tests --data-urlencode in multiple ways | ||||||
|  |  | ||||||
|  | - Fixed --data-urlencode for when no @ or = are used | ||||||
|  |  | ||||||
|  | - Extended the user-agent buffer curl uses, since we can hit the 128 byte | ||||||
|  |   border with plenty development libraries used. Like my current set: "curl | ||||||
|  |   7.17.2-CVS (i686-pc-linux-gnu) libcurl/7.17.2-CVS OpenSSL/0.9.8g | ||||||
|  |   zlib/1.2.3.3 c-ares/1.5.2-CVS libidn/1.1 libssh2/0.19.0-CVS" | ||||||
|  |  | ||||||
|  | Daniel S (24 Nov 2007) | ||||||
|  | - Internal rearrangements, so that the previous struct HandleData is no more. | ||||||
|  |   It is now known as SingleRequest and the Curl_transfer_keeper struct within | ||||||
|  |   that was remove entirely. This has the upside that there are less duplicate | ||||||
|  |   struct members that made it hard to see and remember what struct that was | ||||||
|  |   used to store what data. The transfer_keeper thing was once stored on a | ||||||
|  |   per-connection basis and then it made sense to have the duplicate info but | ||||||
|  |   since it was moved to the SessionHandle (in 7.16.0) it just added weirdness. | ||||||
|  |   The SingleRequest struct is used by data that only is valid for this single | ||||||
|  |   request. | ||||||
|  |  | ||||||
|  | Yang Tse (22 Nov 2007) | ||||||
|  | - Provide a socklen_t definition in curl.h for Win32 API build targets | ||||||
|  |   which don't have one. | ||||||
|  |  | ||||||
|  | Daniel S (22 Nov 2007) | ||||||
|  | - Alessandro Vesely helped me improve the --data-urlencode's syntax, parser | ||||||
|  |   and documentation. | ||||||
|  |  | ||||||
|  | Daniel S (21 Nov 2007) | ||||||
|  | - While inspecting the Negotiate code, I noticed how the proxy auth was using | ||||||
|  |   the same state struct as the host auth, so both could never be used at the | ||||||
|  |   same time! I fixed it (without being able to check) to use two separate | ||||||
|  |   structs to allow authentication using Negotiate on host and proxy | ||||||
|  |   simultaneously. | ||||||
|  |  | ||||||
|  | Daniel S (20 Nov 2007) | ||||||
|  | - Emil Romanus pointed out a bug that made an easy handle get the cookie | ||||||
|  |   engine activated when set to use a share (even if the share doesn't share | ||||||
|  |   cookies). I fixed it. | ||||||
|  |  | ||||||
|  | - Fixed a very long-lasting mprintf() bug that occurred when we did "%.*s%s", | ||||||
|  |   since the second %s would then wrongly used the numerical precision argument | ||||||
|  |   instead and crash. | ||||||
|  |  | ||||||
|  | - Introduced --data-urlencode to the curl tool for easier url encoding of the | ||||||
|  |   data sent in a post. | ||||||
|  |  | ||||||
|  | Daniel S (18 Nov 2007) | ||||||
|  | - Rob Crittenden fixed SSL connections with NSS done with the multi-interface | ||||||
|  |  | ||||||
|  | Daniel S (17 Nov 2007) | ||||||
|  | - Michal Marek made the test suite remember what test servers that fail to | ||||||
|  |   start so that subsequent tries are simply skipped. | ||||||
|  |  | ||||||
|  | - Andres Garcia made the examples build fine on Windows (mingw + msys) when | ||||||
|  |   the lib was built staticly. | ||||||
|  |  | ||||||
|  | Daniel S (16 Nov 2007) | ||||||
|  | - Ates Goral identified a problem in http.c:add_buffer_send() when a debug | ||||||
|  |   callback was used, as it could wrongly pass on a bad size for the outgoing | ||||||
|  |   HTTP header. The bad size would be a very large value as it was a wrapped | ||||||
|  |   size_t content. This happened when the whole HTTP request failed to get sent | ||||||
|  |   in one single send.  http://curl.haxx.se/mail/lib-2007-11/0165.html | ||||||
|  |  | ||||||
|  | Daniel S (15 Nov 2007) | ||||||
|  | - Fixed yet another remaining problem with doing SFTP directory listings on a | ||||||
|  |   re-used persistent connection. Mentioned by Immanuel Gregoire on the mailing | ||||||
|  |   list. | ||||||
|  |  | ||||||
|  | - Michal Marek fixed the test suite to better deal with the case when the HTTP | ||||||
|  |   ipv6 server can't run. | ||||||
|  |  | ||||||
|  | Yang Tse (14 Nov 2007) | ||||||
|  | - Fix a variable potential wrapping in add_buffer() when using absolutely | ||||||
|  |   huge send buffer sizes. | ||||||
|  |  | ||||||
|  | Daniel S (13 Nov 2007) | ||||||
|  | - Fixed a remaining problem with doing SFTP directory listings on a re-used | ||||||
|  |   persistent connection. Mentioned by Immanuel Gregoire on the mailing list. | ||||||
|  |  | ||||||
|  | Daniel S (12 Nov 2007) | ||||||
|  | - Bug report #1830637 (http://curl.haxx.se/bug/view.cgi?id=1830637), which was | ||||||
|  |   forwarded from the Gentoo bug tracker by Daniel Black and was originally | ||||||
|  |   submitted by Robin Johnson, pointed out that libcurl would do bad memory | ||||||
|  |   references when it failed and bailed out before the handler thing was | ||||||
|  |   setup. My fix is not done like the provided patch does it, but instead I | ||||||
|  |   make sure that there's never any chance for a NULL pointer in that struct | ||||||
|  |   member. | ||||||
|  |  | ||||||
|  | Yang Tse (10 Nov 2007) | ||||||
|  | - Vikram Saxena (http://curl.haxx.se/mail/lib-2007-11/0096.html) pointed out | ||||||
|  |   that the pollfd struct was being multi defined when using VS2008. This is | ||||||
|  |   now fixed in /curl/lib/select.h | ||||||
|  |  | ||||||
|  | Daniel S (8 Nov 2007) | ||||||
|  | - Bug report #1823487 (http://curl.haxx.se/bug/view.cgi?id=1823487) pointed | ||||||
|  |   out that SFTP requests didn't use persistent connections. Neither did SCP | ||||||
|  |   ones.  I gave the SSH code a good beating and now both SCP and SFTP should | ||||||
|  |   use persistent connections fine. I also did a bunch of indent changes as | ||||||
|  |   well as a bug fix for the "keyboard interactive" auth. | ||||||
|  |  | ||||||
|  | Dan F (6 Nov 2007) | ||||||
|  | - Improved telnet support by drastically reducing the number of write | ||||||
|  |   callbacks needed to pass a buffer to the user.  Instead one per byte it | ||||||
|  |   is now as little as one per segment. | ||||||
|  |  | ||||||
|  | Yang Tse (6 Nov 2007) | ||||||
|  | - Bug report #1824894 (http://curl.haxx.se/bug/view.cgi?id=1824894) pointed | ||||||
|  |   out a problem in curl.h when building C++ apps with MSVC. To fix it, the | ||||||
|  |   inclusion of header files in curl.h is moved outside of the C++ extern "C" | ||||||
|  |   linkage block. | ||||||
|  |  | ||||||
|  | Daniel S (1 Nov 2007) | ||||||
|  | - Toby Peterson patched a memory problem in the command line tool that | ||||||
|  |   happened when a user had a home dir as an empty string. curl would then do | ||||||
|  |   free() on a wrong area. | ||||||
|  |  | ||||||
|  | Dan F (1 Nov 2007) | ||||||
|  | - Fixed curl-config --features to not display libz when it wasn't used | ||||||
|  |   due to a missing header file. | ||||||
|  |  | ||||||
|  | Dan F (31 October 2007) | ||||||
|  | - Fixed the output of curl-config --protocols which showed SCP and SFTP | ||||||
|  |   always, except when --without-libssh2 was given | ||||||
|  |  | ||||||
|  | - Added test cases 1013 and 1014 to check that curl-config --protocols and | ||||||
|  |   curl-config --features matches the output of curl --version | ||||||
|  |  | ||||||
|  | Dan F (30 October 2007) | ||||||
|  | - Fixed an OOM problem with file: URLs | ||||||
|  |  | ||||||
|  | - Moved Curl_file_connect into the protocol handler struct | ||||||
|  |  | ||||||
|  | Dan F (29 October 2007) | ||||||
|  | - Added test case 546 to check that subsequent FTP transfers work after a | ||||||
|  |   failed one using the multi interface | ||||||
|  |  | ||||||
|  | Daniel S (29 October 2007) | ||||||
|  | - Based on one of those bug reports that are intercepted by a distro's bug | ||||||
|  |   tracker (https://bugzilla.redhat.com/show_bug.cgi?id=316191), I now made | ||||||
|  |   curl-config --features and --protocols show the correct output when built | ||||||
|  |   with NSS. | ||||||
|  |  | ||||||
| Version 7.17.1 (29 October 2007) | Version 7.17.1 (29 October 2007) | ||||||
|  |  | ||||||
| Dan F (25 October 2007) | Dan F (25 October 2007) | ||||||
|   | |||||||
| @@ -10864,7 +10864,7 @@ Version 6.2 | |||||||
|    the configure script to leave SSL alone. The previous functionality has |    the configure script to leave SSL alone. The previous functionality has | ||||||
|    been retained. Troy Engel helped test this new one. |    been retained. Troy Engel helped test this new one. | ||||||
|  |  | ||||||
| Version 6.1 | Version 6.1 (October 17 1999) | ||||||
|  |  | ||||||
|  Daniel (17 October 1999): |  Daniel (17 October 1999): | ||||||
|  - I ifdef'ed or commented all the zlib stuff in the sources and configure |  - I ifdef'ed or commented all the zlib stuff in the sources and configure | ||||||
| @@ -10939,7 +10939,7 @@ Version 6.1beta | |||||||
|  - Made the -F option allow stdin when specifying files. By using '-' instead |  - Made the -F option allow stdin when specifying files. By using '-' instead | ||||||
|    of file name, the data will be read from stdin. |    of file name, the data will be read from stdin. | ||||||
|  |  | ||||||
| Version 6.0 | Version 6.0 (September 14 1999) | ||||||
|  |  | ||||||
|  Daniel (13 September 1999) |  Daniel (13 September 1999) | ||||||
|  - Added -X/--http-request <request> to enable any HTTP command to be sent. |  - Added -X/--http-request <request> to enable any HTTP command to be sent. | ||||||
| @@ -11201,7 +11201,7 @@ Version 5.9.1 | |||||||
|    with form posting where the variable shouldn't have any content, as in curl |    with form posting where the variable shouldn't have any content, as in curl | ||||||
|    -F "form=" www.site.com. It was now fixed. |    -F "form=" www.site.com. It was now fixed. | ||||||
|  |  | ||||||
| Version 5.9 | Version 5.9 (May 22 1999) | ||||||
|  |  | ||||||
|  Daniel (22 May 1999) |  Daniel (22 May 1999) | ||||||
|  - I've got a bug report from Aaron Scarisbrick in which he states he has some |  - I've got a bug report from Aaron Scarisbrick in which he states he has some | ||||||
| @@ -11939,7 +11939,7 @@ Version 4.8.1 | |||||||
|    had nothing but header. Appearantly Solaris deals with negative sizes in |    had nothing but header. Appearantly Solaris deals with negative sizes in | ||||||
|    fwrite() calls a lot better than Linux does... =B-] |    fwrite() calls a lot better than Linux does... =B-] | ||||||
|  |  | ||||||
| Version 4.8 | Version 4.8 (Aug 31, 1998) | ||||||
|  Daniel Stenberg |  Daniel Stenberg | ||||||
|  - Continue FTP file transfer. -c is the switch. Note that you need to |  - Continue FTP file transfer. -c is the switch. Note that you need to | ||||||
|    specify a file name if you wanna resume a download (you can't resume a |    specify a file name if you wanna resume a download (you can't resume a | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								COPYING
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								COPYING
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| COPYRIGHT AND PERMISSION NOTICE | COPYRIGHT AND PERMISSION NOTICE | ||||||
|  |  | ||||||
| Copyright (c) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>. | Copyright (c) 1996 - 2008, Daniel Stenberg, <daniel@haxx.se>. | ||||||
|  |  | ||||||
| All rights reserved. | All rights reserved. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #                            | (__| |_| |  _ <| |___ | #                            | (__| |_| |  _ <| |___ | ||||||
| #                             \___|\___/|_| \_\_____| | #                             \___|\___/|_| \_\_____| | ||||||
| # | # | ||||||
| # Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | # Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -128,6 +128,12 @@ vc: | |||||||
| 	cd ..\src | 	cd ..\src | ||||||
| 	nmake /f Makefile.$(VC) | 	nmake /f Makefile.$(VC) | ||||||
|  |  | ||||||
|  | vc-x64: | ||||||
|  | 	cd lib | ||||||
|  | 	MACHINE=x64 nmake /f Makefile.$(VC) cfg=release | ||||||
|  | 	cd ..\src | ||||||
|  | 	MACHINE=x64 nmake /f Makefile.$(VC) | ||||||
|  |  | ||||||
| vc-zlib: | vc-zlib: | ||||||
| 	cd lib | 	cd lib | ||||||
| 	nmake /f Makefile.$(VC) cfg=release-zlib | 	nmake /f Makefile.$(VC) cfg=release-zlib | ||||||
|   | |||||||
							
								
								
									
										120
									
								
								RELEASE-NOTES
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								RELEASE-NOTES
									
									
									
									
									
								
							| @@ -1,53 +1,68 @@ | |||||||
| Curl and libcurl 7.17.1 | Curl and libcurl 7.18.0 | ||||||
|  |  | ||||||
|  Public curl release number:               102 |  Public curl releases:         103 | ||||||
|  Releases counted from the very beginning: 128 |  Command line options:         126 | ||||||
|  Available command line options:           121 |  curl_easy_setopt() options:   150 | ||||||
|  Available curl_easy_setopt() options:     147 |  Public functions in libcurl:  56 | ||||||
|  Number of public functions in libcurl:    55 |  Public web site mirrors:      43 | ||||||
|  Amount of public web site mirrors:        43 |  Known libcurl bindings:       36 | ||||||
|  Number of known libcurl bindings:         36 |  Contributors:                 597 | ||||||
|  Number of contributors:                   588 |  | ||||||
|  |  | ||||||
| This release includes the following changes: | This release includes the following changes: | ||||||
|   |   | ||||||
|  o automatically append ";type=<a|i>" when using HTTP proxies for FTP urls |  o --data-urlencode | ||||||
|  o improved NSS support |  o CURLOPT_PROXY_TRANSFER_MODE | ||||||
|  o added --proxy-negotiate |  o --no-keepalive - now curl does connections with keep-alive enabled by | ||||||
|  o added --post301 and CURLOPT_POST301 |    default | ||||||
|  o builds with c-ares 1.5.0 |  o --socks4a added (proxy type CURLPROXY_SOCKS4A for libcurl) | ||||||
|  o added CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 and --hostpubmd5 |  o --socks5-hostname added (CURLPROXY_SOCKS5_HOSTNAME for libcurl) | ||||||
|  o renamed CURLE_SSL_PEER_CERTIFICATE to CURLE_PEER_FAILED_VERIFICATION |  o curl_easy_pause() | ||||||
|  o added CURLOPT_OPENSOCKETFUNCTION and CURLOPT_OPENSOCKETDATA |  o CURLOPT_SEEKFUNCTION and CURLOPT_SEEKDATA | ||||||
|  o CULROPT_COOKIELIST supports "FLUSH" |  o --keepalive-time | ||||||
|  o added CURLOPT_COPYPOSTFIELDS |  o curl --help output was re-ordered | ||||||
|  o added --static-libs to curl-config |  | ||||||
|  |  | ||||||
| This release includes the following bugfixes: | This release includes the following bugfixes: | ||||||
|  |  | ||||||
|  o curl-config --protocols now properly reports LDAPS, SCP and SFTP |  o curl-config --features and --protocols show the correct output when built | ||||||
|  o ldapv3 support on Windows |    with NSS, and also when SCP, SFTP and libz are not available | ||||||
|  o ldap builds with the MSVC makefiles |  o free problem in the curl tool for users with empty home dir | ||||||
|  o no HOME and no key given caused SSH auth failure |  o curl.h version 7.17.1 problem when building C++ apps with MSVC | ||||||
|  o Negotiate authentication over proxy |  o SFTP and SCP use persistent connections | ||||||
|  o --ftp-method nocwd on directory listings |  o segfault on bad URL | ||||||
|  o FTP, CURLOPT_NOBODY enabled and CURLOPT_HEADER disabled now does TYPE |  o variable wrapping when using absolutely huge send buffer sizes | ||||||
|    before SIZE |  o variable wrapping when using debug callback and the HTTP request wasn't sent | ||||||
|  o re-used handle transfers with SFTP |    in one go | ||||||
|  o curl_easy_escape() problem with byte values >= 128 |  o SSL connections with NSS done with the multi-interface | ||||||
|  o handles chunked-encoded CONNECT responses |  o setting a share no longer activates cookies | ||||||
|  o misuse of ares_timeout() result |  o Negotiate now works on auth and proxy simultanouesly | ||||||
|  o --local-port on TFTP transfers |  o support HTTP Digest nonces up to 1023 letters | ||||||
|  o CURLOPT_POSTFIELDS could fail to send binary data |  o resumed ftp upload no longer requires the read callback to return full | ||||||
|  o specifying a proxy with a trailing slash didn't work (unless it also |    buffers | ||||||
|    contained a port number) |  o no longer default-appends ;type= on FTP URLs thru proxies | ||||||
|  o redirect from HTTP to FTP or TFTP memory problems and leaks |  o SSL session id caching | ||||||
|  o re-used connections a bit too much when using non-SSL protocols tunneled |  o POST with callback over proxy requiring NTLM or Digest | ||||||
|    over a HTTP proxy |  o Expect: 100-continue flaw on re-used connection with POSTs | ||||||
|  o embed the manifest in VC8 builds |  o build fix for MSVC 9.0 (VS2008) | ||||||
|  o use valgrind in the tests even when the lib is built shared with libtool |  o Windows curl builds failed file truncation when retry downloading | ||||||
|  o libcurl built with NSS can now ignore the peer verification even when the |  o SSL session ID cache memory leak | ||||||
|    ca cert bundle is absent |  o bad connection re-use check with environment variable-activated proxy use | ||||||
|  |  o --libcurl now generates a return statement as well | ||||||
|  |  o socklen_t is no longer used in the public includes | ||||||
|  |  o time zone offsets from -1400 to +1400 are now accepted by the date parser | ||||||
|  |  o allows more spaces in WWW/Proxy-Authenticate: headers | ||||||
|  |  o curl-config --libs skips /usr/lib64 | ||||||
|  |  o range support for file:// transfers | ||||||
|  |  o libcurl hang with huge POST request and request-body read from callback | ||||||
|  |  o removed extra newlines from many error messages | ||||||
|  |  o improved pipelining | ||||||
|  |  o improved OOM handling for data url encoded HTTP POSTs when read from a file | ||||||
|  |  o test suite could pick wrong tool(s) if more than one existed in the PATH | ||||||
|  |  o curl_multi_fdset() failed to return socket while doing CONNECT over proxy | ||||||
|  |  o curl_multi_remove_handle() on a handle that is in used for a pipeline now | ||||||
|  |    break that pipeline | ||||||
|  |  o CURLOPT_COOKIELIST memory leaks | ||||||
|  |  o progress meter/callback during http proxy CONNECT requests | ||||||
|  |  o auth for http proxy when the proxy closes connection after first response | ||||||
|  |  | ||||||
| This release includes the following known bugs: | This release includes the following known bugs: | ||||||
|  |  | ||||||
| @@ -55,18 +70,25 @@ This release includes the following known bugs: | |||||||
|  |  | ||||||
| Other curl-related news: | Other curl-related news: | ||||||
|  |  | ||||||
|  o  |  o TclCurl 7.17.1 => http://personal1.iddeo.es/andresgarci/tclcurl/english/ | ||||||
|  |  o Ruby Curl::Multi 0.1 => http://curl-multi.rubyforge.org/  | ||||||
|  |  o curl-java 0.2.1 => http://curl.haxx.se/libcurl/java/ | ||||||
|  |  | ||||||
| New curl mirrors: | New curl mirrors: | ||||||
|  |  | ||||||
|  o http://curl.wetzlmayr.at/ is a new web mirror in Nuremberg, Germany |  o http://curl.gominet.net/ is new mirror in Vizcaya, Portugal | ||||||
|  |  o http://curl.very-clever.com/ is a new mirror in Nuremberg, Germany | ||||||
|  |  | ||||||
| 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: | ||||||
|  |  | ||||||
|  Dan Fandrich, Michal Marek, G<>nter Knauf, Rob Crittenden, Immanuel Gregoire, |  Dan Fandrich, Gisle Vanem, Toby Peterson, Yang Tse, Daniel Black, | ||||||
|  Mark Davies, Max Katsev, Philip Langdale, Alex Fishman, Johnny Luong, |  Robin Johnson, Michal Marek, Ates Goral, Andres Garcia, Rob Crittenden, | ||||||
|  Alexey Pesternikov, Yang Tse, Kim Rinnewitz, Michael Wallner, |  Emil Romanus, Alessandro Vesely, Ray Pekowski, Spacen Jasset, Andrew Moise, | ||||||
|  Patrick Monnerat, Vladimir Lazarenko |  Gilles Blanc, David Wright, Vikram Saxena, Mateusz Loskot, Gary Maxwell, | ||||||
|  |  Dmitry Kurochkin, Mohun Biswas, Richard Atterer, Maxim Perenesenko, | ||||||
|  |  Daniel Egger, Jeff Johnson, Nikitinskit Dmitriy, Georg Lippitsch, Eric Landes, | ||||||
|  |  Joe Malicki, Nathan Coulter, Lau Hang Kin, Judson Bishop, Igor Franchuk, | ||||||
|  |  Kevin Reed | ||||||
|   |   | ||||||
|         Thanks! (and sorry if I forgot to mention someone) |         Thanks! (and sorry if I forgot to mention someone) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| To be addressed before 7.17.1 (planned release: late October 2007) | To be addressed before 7.18.0 (planned release: January 2008) | ||||||
| ============================= | ============================= | ||||||
|  |  | ||||||
| 106 -  | 118 -  | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								ares/CHANGES
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								ares/CHANGES
									
									
									
									
									
								
							| @@ -1,5 +1,28 @@ | |||||||
|   Changelog for the c-ares project |   Changelog for the c-ares project | ||||||
|  |  | ||||||
|  | * December 11 2007 (Gisle Vanem) | ||||||
|  |  | ||||||
|  | - Added another sample application; acountry.c which converts an | ||||||
|  |   IPv4-address(es) and/or host-name(s) to country-name and country-code. | ||||||
|  |   This uses the service of the DNSBL at countries.nerd.dk. | ||||||
|  |  | ||||||
|  | * December 3 2007 (Daniel Stenberg) | ||||||
|  |  | ||||||
|  | - Brad Spencer fixed the configure script to assume that there's no | ||||||
|  |   /dev/urandom when built cross-compiled as then the script cannot check for | ||||||
|  |   it. | ||||||
|  |  | ||||||
|  | - Erik Kline cleaned up ares_gethostbyaddr.c:next_lookup() somewhat | ||||||
|  |  | ||||||
|  | Version 1.5.1 (Nov 21, 2007) | ||||||
|  |  | ||||||
|  | * November 21 2007 (Daniel Stenberg) | ||||||
|  |  | ||||||
|  | - Robin Cornelius pointed out that ares_llist.h was missing in the release | ||||||
|  |   archive for 1.5.0 | ||||||
|  |  | ||||||
|  | Version 1.5.0 (Nov 21, 2007) | ||||||
|  |  | ||||||
| * October 2 2007 (Daniel Stenberg) | * October 2 2007 (Daniel Stenberg) | ||||||
|  |  | ||||||
| - ares_strerror() segfaulted if the input error number was out of the currently | - ares_strerror() segfaulted if the input error number was out of the currently | ||||||
|   | |||||||
| @@ -8,11 +8,21 @@ MSVCFILES = vc/adig/adig.dep vc/adig/adig.dsp vc/vc.dsw vc/ahost/ahost.dep \ | |||||||
|  vc/ahost/ahost.dsp vc/areslib/areslib.dep vc/areslib/areslib.dsp	   \ |  vc/ahost/ahost.dsp vc/areslib/areslib.dep vc/areslib/areslib.dsp	   \ | ||||||
|  vc/areslib/areslib.dsw |  vc/areslib/areslib.dsw | ||||||
|  |  | ||||||
|  | if DEBUGBUILD | ||||||
|  | PROGS = | ||||||
|  | else | ||||||
|  | PROGS = ahost adig acountry | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | noinst_PROGRAMS =$(PROGS) | ||||||
|  |  | ||||||
| # adig and ahost are just sample programs and thus not mentioned with the | # adig and ahost are just sample programs and thus not mentioned with the | ||||||
| # regular sources and headers | # regular sources and headers | ||||||
| EXTRA_DIST = CHANGES README.cares Makefile.inc adig.c ahost.c $(man_MANS) \ | EXTRA_DIST = CHANGES README.cares Makefile.inc adig.c ahost.c $(man_MANS) \ | ||||||
|  $(MSVCFILES) AUTHORS config-win32.h RELEASE-NOTES libcares.pc.in |  $(MSVCFILES) AUTHORS config-win32.h RELEASE-NOTES libcares.pc.in | ||||||
|  |  | ||||||
|  | pkgconfigdir = $(libdir)/pkgconfig | ||||||
|  | pkgconfig_DATA = libcares.pc | ||||||
|  |  | ||||||
| VER=-version-info 2:0:0 | VER=-version-info 2:0:0 | ||||||
| # This flag accepts an argument of the form current[:revision[:age]]. So, | # This flag accepts an argument of the form current[:revision[:age]]. So, | ||||||
| @@ -61,6 +71,15 @@ libcares_ladir = $(includedir) | |||||||
| # what headers to install on 'make install': | # what headers to install on 'make install': | ||||||
| libcares_la_HEADERS = ares.h ares_version.h ares_dns.h | libcares_la_HEADERS = ares.h ares_version.h ares_dns.h | ||||||
|  |  | ||||||
|  | ahost_SOURCES = ahost.c ares_getopt.c | ||||||
|  | ahost_LDADD = $(top_builddir)/$(lib_LTLIBRARIES) | ||||||
|  |  | ||||||
|  | adig_SOURCES = adig.c ares_getopt.c | ||||||
|  | adig_LDADD = $(top_builddir)/$(lib_LTLIBRARIES) | ||||||
|  |  | ||||||
|  | acountry_SOURCES = acountry.c ares_getopt.c | ||||||
|  | acountry_LDADD = $(top_builddir)/$(lib_LTLIBRARIES) | ||||||
|  |  | ||||||
| # Make files named *.dist replace the file without .dist extension | # Make files named *.dist replace the file without .dist extension | ||||||
| dist-hook: | dist-hook: | ||||||
| 	find $(distdir) -name "*.dist" -exec rm {} \; | 	find $(distdir) -name "*.dist" -exec rm {} \; | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ CFLAGS += -DWATT32 -DHAVE_AF_INET6 -DHAVE_PF_INET6 -DHAVE_FIONBIO \ | |||||||
|           -DRECV_TYPE_ARG1='int'   -DRECV_TYPE_ARG2='void*' \ |           -DRECV_TYPE_ARG1='int'   -DRECV_TYPE_ARG2='void*' \ | ||||||
|           -DRECV_TYPE_ARG3='int'   -DRECV_TYPE_ARG4='int' \ |           -DRECV_TYPE_ARG3='int'   -DRECV_TYPE_ARG4='int' \ | ||||||
|           -DRECV_TYPE_RETV='int'   -DHAVE_STRUCT_TIMEVAL \ |           -DRECV_TYPE_RETV='int'   -DHAVE_STRUCT_TIMEVAL \ | ||||||
|           -Dselect=select_s        -UHAVE_CONFIG_H |           -Dselect=select_s        -Dsocklen_t=int -UHAVE_CONFIG_H | ||||||
|  |  | ||||||
| LDFLAGS = -s | LDFLAGS = -s | ||||||
|  |  | ||||||
| @@ -49,7 +49,7 @@ EX_LIBS += $(WATT32_ROOT)/lib/libwatt.a | |||||||
|  |  | ||||||
| OBJECTS = $(addprefix $(OBJ_DIR)/, $(CSOURCES:.c=.o)) | OBJECTS = $(addprefix $(OBJ_DIR)/, $(CSOURCES:.c=.o)) | ||||||
|  |  | ||||||
| all: $(OBJ_DIR) libcares.a ahost.exe adig.exe | all: $(OBJ_DIR) libcares.a ahost.exe adig.exe acountry.exe | ||||||
| 	@echo Welcome to c-ares. | 	@echo Welcome to c-ares. | ||||||
|  |  | ||||||
| libcares.a: $(OBJECTS) | libcares.a: $(OBJECTS) | ||||||
| @@ -61,11 +61,14 @@ ahost.exe: ahost.c $(OBJ_DIR)/ares_getopt.o $(OBJ_HACK) | |||||||
| adig.exe: adig.c $(OBJ_DIR)/ares_getopt.o $(OBJ_HACK) | adig.exe: adig.c $(OBJ_DIR)/ares_getopt.o $(OBJ_HACK) | ||||||
| 	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(EX_LIBS) | 	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(EX_LIBS) | ||||||
|  |  | ||||||
|  | acountry.exe: acountry.c $(OBJ_DIR)/ares_getopt.o $(OBJ_HACK) | ||||||
|  | 	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(EX_LIBS) | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	rm -f $(OBJECTS) libcares.a | 	rm -f $(OBJECTS) libcares.a | ||||||
|  |  | ||||||
| vclean realclean: clean | vclean realclean: clean | ||||||
| 	rm -f ahost.exe adig.exe depend.dj | 	rm -f ahost.exe adig.exe acountry.exe depend.dj | ||||||
| 	- rmdir $(OBJ_DIR) | 	- rmdir $(OBJ_DIR) | ||||||
|  |  | ||||||
| -include depend.dj | -include depend.dj | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ ares_parse_ns_reply.c ares_llist.c | |||||||
|  |  | ||||||
| HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h          \ | HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h          \ | ||||||
|            nameser.h inet_net_pton.h inet_ntop.h ares_ipv6.h bitncmp.h      \ |            nameser.h inet_net_pton.h inet_ntop.h ares_ipv6.h bitncmp.h      \ | ||||||
|            setup_once.h  |            setup_once.h ares_llist.h | ||||||
|  |  | ||||||
| MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \ | MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \ | ||||||
|  ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3		    \ |  ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3		    \ | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ $(LIB): $(OBJLIB) | |||||||
|  |  | ||||||
| all: $(LIB) demos | all: $(LIB) demos | ||||||
|  |  | ||||||
| demos: adig.exe ahost.exe | demos: adig.exe ahost.exe acountry.exe | ||||||
|  |  | ||||||
| tags: | tags: | ||||||
| 	etags *.[ch] | 	etags *.[ch] | ||||||
| @@ -61,7 +61,7 @@ install: | |||||||
| 	done) | 	done) | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	$(RM) ares_getopt.o $(OBJLIB) $(LIB) adig.exe ahost.exe | 	$(RM) ares_getopt.o $(OBJLIB) $(LIB) adig.exe ahost.exe acountry.exe | ||||||
|  |  | ||||||
| distclean: clean | distclean: clean | ||||||
| 	$(RM) config.cache config.log config.status Makefile | 	$(RM) config.cache config.log config.status Makefile | ||||||
|   | |||||||
| @@ -18,10 +18,10 @@ INSTDIR	= ../curl-$(LIBCURL_VERSION_STR)-bin-nw | |||||||
| endif | endif | ||||||
|  |  | ||||||
| # Edit the vars below to change NLM target settings. | # Edit the vars below to change NLM target settings. | ||||||
| TARGETS = adig.nlm ahost.nlm | TARGETS = adig.nlm ahost.nlm acountry.nlm | ||||||
| LTARGET = libcares.$(LIBEXT) | LTARGET = libcares.$(LIBEXT) | ||||||
| VERSION	= $(LIBCARES_VERSION) | VERSION	= $(LIBCARES_VERSION) | ||||||
| COPYR	= Copyright (C) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se> | COPYR	= Copyright (C) 1996 - 2008, Daniel Stenberg, <daniel@haxx.se> | ||||||
| DESCR	= cURL $(subst .def,,$(notdir $@)) $(LIBCARES_VERSION_STR) - http://curl.haxx.se | DESCR	= cURL $(subst .def,,$(notdir $@)) $(LIBCARES_VERSION_STR) - http://curl.haxx.se | ||||||
| MTSAFE	= YES | MTSAFE	= YES | ||||||
| STACK	= 64000 | STACK	= 64000 | ||||||
| @@ -300,7 +300,6 @@ ifeq ($(LIBARCH),CLIB) | |||||||
| 	@echo $(DL)#define SEND_TYPE_ARG3 int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_ARG3 int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SEND_TYPE_RETV int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_RETV int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define DL_LDAP_FILE "ldapsdk.nlm"$(DL) >> $@ |  | ||||||
| 	@echo $(DL)#define socklen_t int$(DL) >> $@ | 	@echo $(DL)#define socklen_t int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define strncasecmp strnicmp$(DL) >> $@ | 	@echo $(DL)#define strncasecmp strnicmp$(DL) >> $@ | ||||||
| 	@echo $(DL)#define strcasecmp stricmp$(DL) >> $@ | 	@echo $(DL)#define strcasecmp stricmp$(DL) >> $@ | ||||||
| @@ -338,7 +337,6 @@ else | |||||||
| 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SEND_TYPE_RETV ssize_t$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_RETV ssize_t$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SIZEOF_STRUCT_IN6_ADDR 16$(DL) >> $@ | 	@echo $(DL)#define SIZEOF_STRUCT_IN6_ADDR 16$(DL) >> $@ | ||||||
| 	@echo $(DL)#define DL_LDAP_FILE "lldapsdk.nlm"$(DL) >> $@ |  | ||||||
| endif | endif | ||||||
| 	@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@ | 	@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@ | ||||||
| 	@echo $(DL)#define HAVE_ARPA_NAMESER_H 1$(DL) >> $@ | 	@echo $(DL)#define HAVE_ARPA_NAMESER_H 1$(DL) >> $@ | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ OBJECTS = $(OBJ_DIR)\ares_fds.obj              \ | |||||||
|           $(OBJ_DIR)\inet_net_pton.obj         \ |           $(OBJ_DIR)\inet_net_pton.obj         \ | ||||||
|           $(OBJ_DIR)\inet_ntop.obj |           $(OBJ_DIR)\inet_ntop.obj | ||||||
|  |  | ||||||
| all: $(OBJ_DIR) cares.lib cares.dll cares_imp.lib ahost.exe adig.exe | all: $(OBJ_DIR) cares.lib cares.dll cares_imp.lib ahost.exe adig.exe acountry.exe | ||||||
|        @echo Welcome to c-ares library and examples |        @echo Welcome to c-ares library and examples | ||||||
|  |  | ||||||
| $(OBJ_DIR): | $(OBJ_DIR): | ||||||
| @@ -131,6 +131,9 @@ ahost.exe: $(OBJ_DIR) $(OBJ_DIR)\ahost.obj $(OBJ_DIR)\ares_getopt.obj cares_imp. | |||||||
| adig.exe: $(OBJ_DIR) $(OBJ_DIR)\adig.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib | adig.exe: $(OBJ_DIR) $(OBJ_DIR)\adig.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib | ||||||
|        link $(LDFLAGS) -out:$@ $(OBJ_DIR)\adig.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib $(EX_LIBS) |        link $(LDFLAGS) -out:$@ $(OBJ_DIR)\adig.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib $(EX_LIBS) | ||||||
|  |  | ||||||
|  | acountry.exe: $(OBJ_DIR) $(OBJ_DIR)\acountry.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib | ||||||
|  |        link $(LDFLAGS) -out:$@ $(OBJ_DIR)\acountry.obj $(OBJ_DIR)\ares_getopt.obj cares_imp.lib $(EX_LIBS) | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
|        - del $(OBJ_DIR)\*.obj *.ilk *.pdb *.pbt *.pbi *.pbo *._xe *.map |        - del $(OBJ_DIR)\*.obj *.ilk *.pdb *.pbt *.pbi *.pbo *._xe *.map | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| This is what's new and changed in the c-ares 1.4.1 release: | This is what's new and changed in the c-ares 1.5.2 release: | ||||||
|  |  | ||||||
|  o  |  o  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										589
									
								
								ares/acountry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										589
									
								
								ares/acountry.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,589 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * IP-address/hostname to country converter. | ||||||
|  |  * | ||||||
|  |  * Problem; you want to know where IP a.b.c.d is located. | ||||||
|  |  * | ||||||
|  |  * Use ares_gethostbyname ("d.c.b.a.zz.countries.nerd.dk") | ||||||
|  |  * and get the CNAME (host->h_name). Result will be: | ||||||
|  |  *   CNAME = zz<CC>.countries.nerd.dk with address 127.0.x.y (ver 1) or | ||||||
|  |  *   CNAME = <a.b.c.d>.zz.countries.nerd.dk with address 127.0.x.y (ver 2) | ||||||
|  |  * | ||||||
|  |  * The 2 letter country code in <CC> and the ISO-3166 country | ||||||
|  |  * number in x.y (number = x*256 + y). Version 2 of the protocol is missing | ||||||
|  |  * the <CC> number. | ||||||
|  |  * | ||||||
|  |  * Ref: http://countries.nerd.dk/more.html | ||||||
|  |  * | ||||||
|  |  * Written by G. Vanem <gvanem@broadpark.no> 2006, 2007 | ||||||
|  |  * | ||||||
|  |  * NB! This program may not be big-endian aware. | ||||||
|  |  * | ||||||
|  |  * Permission to use, copy, modify, and distribute this | ||||||
|  |  * software and its documentation for any purpose and without | ||||||
|  |  * fee is hereby granted, provided that the above copyright | ||||||
|  |  * notice appear in all copies and that both that copyright | ||||||
|  |  * notice and this permission notice appear in supporting | ||||||
|  |  * documentation, and that the name of M.I.T. not be used in | ||||||
|  |  * advertising or publicity pertaining to distribution of the | ||||||
|  |  * software without specific, written prior permission. | ||||||
|  |  * M.I.T. makes no representations about the suitability of | ||||||
|  |  * this software for any purpose.  It is provided "as is" | ||||||
|  |  * without express or implied warranty. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <ctype.h> | ||||||
|  | #ifdef HAVE_UNISTD_H | ||||||
|  | #include <unistd.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(WIN32) | ||||||
|  |   #include <winsock.h> | ||||||
|  | #else | ||||||
|  |   #include <arpa/inet.h> | ||||||
|  |   #include <netinet/in.h> | ||||||
|  |   #include <netdb.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include "ares.h" | ||||||
|  | #include "ares_getopt.h" | ||||||
|  | #include "inet_net_pton.h" | ||||||
|  | #include "inet_ntop.h" | ||||||
|  |  | ||||||
|  | static const char *usage      = "acountry [-vh?] {host|addr} ...\n"; | ||||||
|  | static const char  nerd_fmt[] = "%u.%u.%u.%u.zz.countries.nerd.dk"; | ||||||
|  | static const char *nerd_ver1  = nerd_fmt + 14; | ||||||
|  | static const char *nerd_ver2  = nerd_fmt + 11; | ||||||
|  | static int         verbose    = 0; | ||||||
|  |  | ||||||
|  | #define TRACE(fmt) do {               \ | ||||||
|  |                      if (verbose > 0) \ | ||||||
|  |                        printf fmt ;   \ | ||||||
|  |                    } while (0) | ||||||
|  |  | ||||||
|  | static void wait_ares(ares_channel channel); | ||||||
|  | static void callback(void *arg, int status, int timeouts, struct hostent *host); | ||||||
|  | static void callback2(void *arg, int status, int timeouts, struct hostent *host); | ||||||
|  | static void find_country_from_cname(const char *cname, struct in_addr addr); | ||||||
|  |  | ||||||
|  | static void Abort(const char *fmt, ...) | ||||||
|  | { | ||||||
|  |   va_list args; | ||||||
|  |   va_start(args, fmt); | ||||||
|  |   vfprintf(stderr, fmt, args); | ||||||
|  |   va_end(args); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |   ares_channel channel; | ||||||
|  |   int    ch, status; | ||||||
|  |  | ||||||
|  | #ifdef WIN32 | ||||||
|  |   WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); | ||||||
|  |   WSADATA wsaData; | ||||||
|  |   WSAStartup(wVersionRequested, &wsaData); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   while ((ch = ares_getopt(argc, argv, "dvh?")) != -1) | ||||||
|  |     switch (ch) | ||||||
|  |       { | ||||||
|  |       case 'd': | ||||||
|  | #ifdef WATT32 | ||||||
|  |         dbug_init(); | ||||||
|  | #endif | ||||||
|  |         break; | ||||||
|  |       case 'v': | ||||||
|  |         verbose++; | ||||||
|  |         break; | ||||||
|  |       case 'h': | ||||||
|  |       case '?': | ||||||
|  |       default: | ||||||
|  |         Abort(usage); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |   argc -= optind; | ||||||
|  |   argv += optind; | ||||||
|  |   if (argc < 1) | ||||||
|  |      Abort(usage); | ||||||
|  |  | ||||||
|  |   status = ares_init(&channel); | ||||||
|  |   if (status != ARES_SUCCESS) | ||||||
|  |     { | ||||||
|  |       fprintf(stderr, "ares_init: %s\n", ares_strerror(status)); | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   /* Initiate the queries, one per command-line argument. */ | ||||||
|  |   for ( ; *argv; argv++) | ||||||
|  |     { | ||||||
|  |       struct in_addr addr; | ||||||
|  |       char buf[100]; | ||||||
|  |  | ||||||
|  |       /* If this fails, assume '*argv' is a host-name that | ||||||
|  |        * must be resolved first | ||||||
|  |        */ | ||||||
|  |       if (ares_inet_pton(AF_INET, *argv, &addr) != 1) | ||||||
|  |         { | ||||||
|  |           ares_gethostbyname(channel, *argv, AF_INET, callback2, &addr); | ||||||
|  |           wait_ares(channel); | ||||||
|  |           if (addr.s_addr == INADDR_NONE) | ||||||
|  |             { | ||||||
|  |               printf("Failed to lookup %s\n", *argv); | ||||||
|  |               continue; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |       sprintf(buf, nerd_fmt, | ||||||
|  |               (unsigned int)(addr.s_addr >> 24), | ||||||
|  |               (unsigned int)((addr.s_addr >> 16) & 255), | ||||||
|  |               (unsigned int)((addr.s_addr >> 8) & 255), | ||||||
|  |               (unsigned int)(addr.s_addr & 255)); | ||||||
|  |       TRACE(("Looking up %s...", buf)); | ||||||
|  |       fflush(stdout); | ||||||
|  |       ares_gethostbyname(channel, buf, AF_INET, callback, buf); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   wait_ares(channel); | ||||||
|  |   ares_destroy(channel); | ||||||
|  |  | ||||||
|  | #ifdef WIN32 | ||||||
|  |   WSACleanup(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Wait for the queries to complete. | ||||||
|  |  */ | ||||||
|  | static void wait_ares(ares_channel channel) | ||||||
|  | { | ||||||
|  |   while (1) | ||||||
|  |     { | ||||||
|  |       struct timeval *tvp, tv; | ||||||
|  |       fd_set read_fds, write_fds; | ||||||
|  |       int nfds; | ||||||
|  |  | ||||||
|  |       FD_ZERO(&read_fds); | ||||||
|  |       FD_ZERO(&write_fds); | ||||||
|  |       nfds = ares_fds(channel, &read_fds, &write_fds); | ||||||
|  |       if (nfds == 0) | ||||||
|  |         break; | ||||||
|  |       tvp = ares_timeout(channel, NULL, &tv); | ||||||
|  |       select(nfds, &read_fds, &write_fds, NULL, tvp); | ||||||
|  |       ares_process(channel, &read_fds, &write_fds); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This is the callback used when we have the IP-address of interest. | ||||||
|  |  * Extract the CNAME and figure out the country-code from it. | ||||||
|  |  */ | ||||||
|  | static void callback(void *arg, int status, int timeouts, struct hostent *host) | ||||||
|  | { | ||||||
|  |   const char *name = (const char*)arg; | ||||||
|  |   const char *cname; | ||||||
|  |   char buf[20]; | ||||||
|  |  | ||||||
|  |   (void)timeouts; | ||||||
|  |  | ||||||
|  |   if (!host || status != ARES_SUCCESS) | ||||||
|  |     { | ||||||
|  |       printf("Failed to lookup %s: %s\n", name, ares_strerror(status)); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   TRACE(("\nFound address %s, name %s\n", | ||||||
|  |          ares_inet_ntop(AF_INET,(const char*)host->h_addr,buf,sizeof(buf)), | ||||||
|  |          host->h_name)); | ||||||
|  |  | ||||||
|  |   cname = host->h_name;  /* CNAME gets put here */ | ||||||
|  |   if (!cname) | ||||||
|  |     printf("Failed to get CNAME for %s\n", name); | ||||||
|  |   else | ||||||
|  |     find_country_from_cname(cname, *(struct in_addr*)host->h_addr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This is the callback used to obtain the IP-address of the host of interest. | ||||||
|  |  */ | ||||||
|  | static void callback2(void *arg, int status, int timeouts, struct hostent *host) | ||||||
|  | { | ||||||
|  |   struct in_addr *addr = (struct in_addr*) arg; | ||||||
|  |  | ||||||
|  |   (void)timeouts; | ||||||
|  |   if (!host || status != ARES_SUCCESS) | ||||||
|  |     memset(addr, INADDR_NONE, sizeof(*addr)); | ||||||
|  |   else | ||||||
|  |     memcpy(addr, host->h_addr, sizeof(*addr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct search_list { | ||||||
|  |        int         country_number; /* ISO-3166 country number */ | ||||||
|  |        char        short_name[3];  /* A2 short country code */ | ||||||
|  |        const char *long_name;      /* normal country name */ | ||||||
|  |      }; | ||||||
|  |  | ||||||
|  | const struct search_list *list_lookup(int number, const struct search_list *list, int num) | ||||||
|  | { | ||||||
|  |   while (num > 0 && list->long_name) | ||||||
|  |     { | ||||||
|  |       if (list->country_number == number) | ||||||
|  |         return (list); | ||||||
|  |       num--; | ||||||
|  |       list++; | ||||||
|  |     } | ||||||
|  |   return (NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Ref: ftp://ftp.ripe.net/iso3166-countrycodes.txt | ||||||
|  |  */ | ||||||
|  | static const struct search_list country_list[] = { | ||||||
|  |        {   4, "af", "Afghanistan"                          }, | ||||||
|  |        { 248, "ax", "<EFBFBD>land Island"                         }, | ||||||
|  |        {   8, "al", "Albania"                              }, | ||||||
|  |        {  12, "dz", "Algeria"                              }, | ||||||
|  |        {  16, "as", "American Samoa"                       }, | ||||||
|  |        {  20, "ad", "Andorra"                              }, | ||||||
|  |        {  24, "ao", "Angola"                               }, | ||||||
|  |        { 660, "ai", "Anguilla"                             }, | ||||||
|  |        {  10, "aq", "Antarctica"                           }, | ||||||
|  |        {  28, "ag", "Antigua & Barbuda"                    }, | ||||||
|  |        {  32, "ar", "Argentina"                            }, | ||||||
|  |        {  51, "am", "Armenia"                              }, | ||||||
|  |        { 533, "aw", "Aruba"                                }, | ||||||
|  |        {  36, "au", "Australia"                            }, | ||||||
|  |        {  40, "at", "Austria"                              }, | ||||||
|  |        {  31, "az", "Azerbaijan"                           }, | ||||||
|  |        {  44, "bs", "Bahamas"                              }, | ||||||
|  |        {  48, "bh", "Bahrain"                              }, | ||||||
|  |        {  50, "bd", "Bangladesh"                           }, | ||||||
|  |        {  52, "bb", "Barbados"                             }, | ||||||
|  |        { 112, "by", "Belarus"                              }, | ||||||
|  |        {  56, "be", "Belgium"                              }, | ||||||
|  |        {  84, "bz", "Belize"                               }, | ||||||
|  |        { 204, "bj", "Benin"                                }, | ||||||
|  |        {  60, "bm", "Bermuda"                              }, | ||||||
|  |        {  64, "bt", "Bhutan"                               }, | ||||||
|  |        {  68, "bo", "Bolivia"                              }, | ||||||
|  |        {  70, "ba", "Bosnia & Herzegowina"                 }, | ||||||
|  |        {  72, "bw", "Botswana"                             }, | ||||||
|  |        {  74, "bv", "Bouvet Island"                        }, | ||||||
|  |        {  76, "br", "Brazil"                               }, | ||||||
|  |        {  86, "io", "British Indian Ocean Territory"       }, | ||||||
|  |        {  96, "bn", "Brunei Darussalam"                    }, | ||||||
|  |        { 100, "bg", "Bulgaria"                             }, | ||||||
|  |        { 854, "bf", "Burkina Faso"                         }, | ||||||
|  |        { 108, "bi", "Burundi"                              }, | ||||||
|  |        { 116, "kh", "Cambodia"                             }, | ||||||
|  |        { 120, "cm", "Cameroon"                             }, | ||||||
|  |        { 124, "ca", "Canada"                               }, | ||||||
|  |        { 132, "cv", "Cape Verde"                           }, | ||||||
|  |        { 136, "ky", "Cayman Islands"                       }, | ||||||
|  |        { 140, "cf", "Central African Republic"             }, | ||||||
|  |        { 148, "td", "Chad"                                 }, | ||||||
|  |        { 152, "cl", "Chile"                                }, | ||||||
|  |        { 156, "cn", "China"                                }, | ||||||
|  |        { 162, "cx", "Christmas Island"                     }, | ||||||
|  |        { 166, "cc", "Cocos Islands"                        }, | ||||||
|  |        { 170, "co", "Colombia"                             }, | ||||||
|  |        { 174, "km", "Comoros"                              }, | ||||||
|  |        { 178, "cg", "Congo"                                }, | ||||||
|  |        { 180, "cd", "Congo"                                }, | ||||||
|  |        { 184, "ck", "Cook Islands"                         }, | ||||||
|  |        { 188, "cr", "Costa Rica"                           }, | ||||||
|  |        { 384, "ci", "Cote d'Ivoire"                        }, | ||||||
|  |        { 191, "hr", "Croatia"                              }, | ||||||
|  |        { 192, "cu", "Cuba"                                 }, | ||||||
|  |        { 196, "cy", "Cyprus"                               }, | ||||||
|  |        { 203, "cz", "Czech Republic"                       }, | ||||||
|  |        { 208, "dk", "Denmark"                              }, | ||||||
|  |        { 262, "dj", "Djibouti"                             }, | ||||||
|  |        { 212, "dm", "Dominica"                             }, | ||||||
|  |        { 214, "do", "Dominican Republic"                   }, | ||||||
|  |        { 218, "ec", "Ecuador"                              }, | ||||||
|  |        { 818, "eg", "Egypt"                                }, | ||||||
|  |        { 222, "sv", "El Salvador"                          }, | ||||||
|  |        { 226, "gq", "Equatorial Guinea"                    }, | ||||||
|  |        { 232, "er", "Eritrea"                              }, | ||||||
|  |        { 233, "ee", "Estonia"                              }, | ||||||
|  |        { 231, "et", "Ethiopia"                             }, | ||||||
|  |        { 238, "fk", "Falkland Islands"                     }, | ||||||
|  |        { 234, "fo", "Faroe Islands"                        }, | ||||||
|  |        { 242, "fj", "Fiji"                                 }, | ||||||
|  |        { 246, "fi", "Finland"                              }, | ||||||
|  |        { 250, "fr", "France"                               }, | ||||||
|  |        { 249, "fx", "France, Metropolitan"                 }, | ||||||
|  |        { 254, "gf", "French Guiana"                        }, | ||||||
|  |        { 258, "pf", "French Polynesia"                     }, | ||||||
|  |        { 260, "tf", "French Southern Territories"          }, | ||||||
|  |        { 266, "ga", "Gabon"                                }, | ||||||
|  |        { 270, "gm", "Gambia"                               }, | ||||||
|  |        { 268, "ge", "Georgia"                              }, | ||||||
|  |        { 276, "de", "Germany"                              }, | ||||||
|  |        { 288, "gh", "Ghana"                                }, | ||||||
|  |        { 292, "gi", "Gibraltar"                            }, | ||||||
|  |        { 300, "gr", "Greece"                               }, | ||||||
|  |        { 304, "gl", "Greenland"                            }, | ||||||
|  |        { 308, "gd", "Grenada"                              }, | ||||||
|  |        { 312, "gp", "Guadeloupe"                           }, | ||||||
|  |        { 316, "gu", "Guam"                                 }, | ||||||
|  |        { 320, "gt", "Guatemala"                            }, | ||||||
|  |        { 324, "gn", "Guinea"                               }, | ||||||
|  |        { 624, "gw", "Guinea-Bissau"                        }, | ||||||
|  |        { 328, "gy", "Guyana"                               }, | ||||||
|  |        { 332, "ht", "Haiti"                                }, | ||||||
|  |        { 334, "hm", "Heard & Mc Donald Islands"            }, | ||||||
|  |        { 336, "va", "Vatican City"                         }, | ||||||
|  |        { 340, "hn", "Honduras"                             }, | ||||||
|  |        { 344, "hk", "Hong kong"                            }, | ||||||
|  |        { 348, "hu", "Hungary"                              }, | ||||||
|  |        { 352, "is", "Iceland"                              }, | ||||||
|  |        { 356, "in", "India"                                }, | ||||||
|  |        { 360, "id", "Indonesia"                            }, | ||||||
|  |        { 364, "ir", "Iran"                                 }, | ||||||
|  |        { 368, "iq", "Iraq"                                 }, | ||||||
|  |        { 372, "ie", "Ireland"                              }, | ||||||
|  |        { 376, "il", "Israel"                               }, | ||||||
|  |        { 380, "it", "Italy"                                }, | ||||||
|  |        { 388, "jm", "Jamaica"                              }, | ||||||
|  |        { 392, "jp", "Japan"                                }, | ||||||
|  |        { 400, "jo", "Jordan"                               }, | ||||||
|  |        { 398, "kz", "Kazakhstan"                           }, | ||||||
|  |        { 404, "ke", "Kenya"                                }, | ||||||
|  |        { 296, "ki", "Kiribati"                             }, | ||||||
|  |        { 408, "kp", "Korea (north)"                        }, | ||||||
|  |        { 410, "kr", "Korea (south)"                        }, | ||||||
|  |        { 414, "kw", "Kuwait"                               }, | ||||||
|  |        { 417, "kg", "Kyrgyzstan"                           }, | ||||||
|  |        { 418, "la", "Laos"                                 }, | ||||||
|  |        { 428, "lv", "Latvia"                               }, | ||||||
|  |        { 422, "lb", "Lebanon"                              }, | ||||||
|  |        { 426, "ls", "Lesotho"                              }, | ||||||
|  |        { 430, "lr", "Liberia"                              }, | ||||||
|  |        { 434, "ly", "Libya"                                }, | ||||||
|  |        { 438, "li", "Liechtenstein"                        }, | ||||||
|  |        { 440, "lt", "Lithuania"                            }, | ||||||
|  |        { 442, "lu", "Luxembourg"                           }, | ||||||
|  |        { 446, "mo", "Macao"                                }, | ||||||
|  |        { 807, "mk", "Macedonia"                            }, | ||||||
|  |        { 450, "mg", "Madagascar"                           }, | ||||||
|  |        { 454, "mw", "Malawi"                               }, | ||||||
|  |        { 458, "my", "Malaysia"                             }, | ||||||
|  |        { 462, "mv", "Maldives"                             }, | ||||||
|  |        { 466, "ml", "Mali"                                 }, | ||||||
|  |        { 470, "mt", "Malta"                                }, | ||||||
|  |        { 584, "mh", "Marshall Islands"                     }, | ||||||
|  |        { 474, "mq", "Martinique"                           }, | ||||||
|  |        { 478, "mr", "Mauritania"                           }, | ||||||
|  |        { 480, "mu", "Mauritius"                            }, | ||||||
|  |        { 175, "yt", "Mayotte"                              }, | ||||||
|  |        { 484, "mx", "Mexico"                               }, | ||||||
|  |        { 583, "fm", "Micronesia"                           }, | ||||||
|  |        { 498, "md", "Moldova"                              }, | ||||||
|  |        { 492, "mc", "Monaco"                               }, | ||||||
|  |        { 496, "mn", "Mongolia"                             }, | ||||||
|  |        { 500, "ms", "Montserrat"                           }, | ||||||
|  |        { 504, "ma", "Morocco"                              }, | ||||||
|  |        { 508, "mz", "Mozambique"                           }, | ||||||
|  |        { 104, "mm", "Myanmar"                              }, | ||||||
|  |        { 516, "na", "Namibia"                              }, | ||||||
|  |        { 520, "nr", "Nauru"                                }, | ||||||
|  |        { 524, "np", "Nepal"                                }, | ||||||
|  |        { 528, "nl", "Netherlands"                          }, | ||||||
|  |        { 530, "an", "Netherlands Antilles"                 }, | ||||||
|  |        { 540, "nc", "New Caledonia"                        }, | ||||||
|  |        { 554, "nz", "New Zealand"                          }, | ||||||
|  |        { 558, "ni", "Nicaragua"                            }, | ||||||
|  |        { 562, "ne", "Niger"                                }, | ||||||
|  |        { 566, "ng", "Nigeria"                              }, | ||||||
|  |        { 570, "nu", "Niue"                                 }, | ||||||
|  |        { 574, "nf", "Norfolk Island"                       }, | ||||||
|  |        { 580, "mp", "Northern Mariana Islands"             }, | ||||||
|  |        { 578, "no", "Norway"                               }, | ||||||
|  |        { 512, "om", "Oman"                                 }, | ||||||
|  |        { 586, "pk", "Pakistan"                             }, | ||||||
|  |        { 585, "pw", "Palau"                                }, | ||||||
|  |        { 275, "ps", "Palestinian Territory"                }, | ||||||
|  |        { 591, "pa", "Panama"                               }, | ||||||
|  |        { 598, "pg", "Papua New Guinea"                     }, | ||||||
|  |        { 600, "py", "Paraguay"                             }, | ||||||
|  |        { 604, "pe", "Peru"                                 }, | ||||||
|  |        { 608, "ph", "Philippines"                          }, | ||||||
|  |        { 612, "pn", "Pitcairn"                             }, | ||||||
|  |        { 616, "pl", "Poland"                               }, | ||||||
|  |        { 620, "pt", "Portugal"                             }, | ||||||
|  |        { 630, "pr", "Puerto Rico"                          }, | ||||||
|  |        { 634, "qa", "Qatar"                                }, | ||||||
|  |        { 638, "re", "Reunion"                              }, | ||||||
|  |        { 642, "ro", "Romania"                              }, | ||||||
|  |        { 643, "ru", "Russia"                               }, | ||||||
|  |        { 646, "rw", "Rwanda"                               }, | ||||||
|  |        { 659, "kn", "Saint Kitts & Nevis"                  }, | ||||||
|  |        { 662, "lc", "Saint Lucia"                          }, | ||||||
|  |        { 670, "vc", "Saint Vincent"                        }, | ||||||
|  |        { 882, "ws", "Samoa"                                }, | ||||||
|  |        { 674, "sm", "San Marino"                           }, | ||||||
|  |        { 678, "st", "Sao Tome & Principe"                  }, | ||||||
|  |        { 682, "sa", "Saudi Arabia"                         }, | ||||||
|  |        { 686, "sn", "Senegal"                              }, | ||||||
|  |        { 891, "cs", "Serbia and Montenegro"                }, | ||||||
|  |        { 690, "sc", "Seychelles"                           }, | ||||||
|  |        { 694, "sl", "Sierra Leone"                         }, | ||||||
|  |        { 702, "sg", "Singapore"                            }, | ||||||
|  |        { 703, "sk", "Slovakia"                             }, | ||||||
|  |        { 705, "si", "Slovenia"                             }, | ||||||
|  |        {  90, "sb", "Solomon Islands"                      }, | ||||||
|  |        { 706, "so", "Somalia"                              }, | ||||||
|  |        { 710, "za", "South Africa"                         }, | ||||||
|  |        { 239, "gs", "South Georgia"                        }, | ||||||
|  |        { 724, "es", "Spain"                                }, | ||||||
|  |        { 144, "lk", "Sri Lanka"                            }, | ||||||
|  |        { 654, "sh", "St. Helena"                           }, | ||||||
|  |        { 666, "pm", "St. Pierre & Miquelon"                }, | ||||||
|  |        { 736, "sd", "Sudan"                                }, | ||||||
|  |        { 740, "sr", "Suriname"                             }, | ||||||
|  |        { 744, "sj", "Svalbard & Jan Mayen Islands"         }, | ||||||
|  |        { 748, "sz", "Swaziland"                            }, | ||||||
|  |        { 752, "se", "Sweden"                               }, | ||||||
|  |        { 756, "ch", "Switzerland"                          }, | ||||||
|  |        { 760, "sy", "Syrian Arab Republic"                 }, | ||||||
|  |        { 626, "tl", "Timor-Leste"                          }, | ||||||
|  |        { 158, "tw", "Taiwan"                               }, | ||||||
|  |        { 762, "tj", "Tajikistan"                           }, | ||||||
|  |        { 834, "tz", "Tanzania"                             }, | ||||||
|  |        { 764, "th", "Thailand"                             }, | ||||||
|  |        { 768, "tg", "Togo"                                 }, | ||||||
|  |        { 772, "tk", "Tokelau"                              }, | ||||||
|  |        { 776, "to", "Tonga"                                }, | ||||||
|  |        { 780, "tt", "Trinidad & Tobago"                    }, | ||||||
|  |        { 788, "tn", "Tunisia"                              }, | ||||||
|  |        { 792, "tr", "Turkey"                               }, | ||||||
|  |        { 795, "tm", "Turkmenistan"                         }, | ||||||
|  |        { 796, "tc", "Turks & Caicos Islands"               }, | ||||||
|  |        { 798, "tv", "Tuvalu"                               }, | ||||||
|  |        { 800, "ug", "Uganda"                               }, | ||||||
|  |        { 804, "ua", "Ukraine"                              }, | ||||||
|  |        { 784, "ae", "United Arab Emirates"                 }, | ||||||
|  |        { 826, "gb", "United Kingdom"                       }, | ||||||
|  |        { 840, "us", "United States"                        }, | ||||||
|  |        { 581, "um", "United States Minor Outlying Islands" }, | ||||||
|  |        { 858, "uy", "Uruguay"                              }, | ||||||
|  |        { 860, "uz", "Uzbekistan"                           }, | ||||||
|  |        { 548, "vu", "Vanuatu"                              }, | ||||||
|  |        { 862, "ve", "Venezuela"                            }, | ||||||
|  |        { 704, "vn", "Vietnam"                              }, | ||||||
|  |        {  92, "vg", "Virgin Islands (British)"             }, | ||||||
|  |        { 850, "vi", "Virgin Islands (US)"                  }, | ||||||
|  |        { 876, "wf", "Wallis & Futuna Islands"              }, | ||||||
|  |        { 732, "eh", "Western Sahara"                       }, | ||||||
|  |        { 887, "ye", "Yemen"                                }, | ||||||
|  |        { 894, "zm", "Zambia"                               }, | ||||||
|  |        { 716, "zw", "Zimbabwe"                             } | ||||||
|  |      }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Check if start of 'str' is simply an IPv4 address. | ||||||
|  |  */ | ||||||
|  | #define BYTE_OK(x) ((x) >= 0 && (x) <= 255) | ||||||
|  |  | ||||||
|  | static int is_addr(char *str, char **end) | ||||||
|  | { | ||||||
|  |   int a0, a1, a2, a3, num, rc = 0, length = 0; | ||||||
|  |  | ||||||
|  |   if ((num = sscanf(str,"%3d.%3d.%3d.%3d%n",&a0,&a1,&a2,&a3,&length)) == 4 && | ||||||
|  |       BYTE_OK(a0) && BYTE_OK(a1) && BYTE_OK(a2) && BYTE_OK(a3) && | ||||||
|  |       length >= (3+4)) | ||||||
|  |     { | ||||||
|  |       rc = 1; | ||||||
|  |       *end = str + length; | ||||||
|  |     } | ||||||
|  |   return rc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Find the country-code and name from the CNAME. E.g.: | ||||||
|  |  *   version 1: CNAME = zzno.countries.nerd.dk with address 127.0.2.66 | ||||||
|  |  *              yields ccode_A" = "no" and cnumber 578 (2.66). | ||||||
|  |  *   version 2: CNAME = <a.b.c.d>.zz.countries.nerd.dk with address 127.0.2.66 | ||||||
|  |  *              yields cnumber 578 (2.66). ccode_A is ""; | ||||||
|  |  */ | ||||||
|  | static void find_country_from_cname(const char *cname, struct in_addr addr) | ||||||
|  | { | ||||||
|  |   const struct search_list *country; | ||||||
|  |   char  ccode_A2[3], *ccopy, *dot_4; | ||||||
|  |   int   cnumber, z0, z1, ver_1, ver_2; | ||||||
|  |   u_long ip; | ||||||
|  |  | ||||||
|  |   ip = ntohl(addr.s_addr); | ||||||
|  |   z0 = tolower(cname[0]); | ||||||
|  |   z1 = tolower(cname[1]); | ||||||
|  |   ccopy = strdup(cname); | ||||||
|  |  | ||||||
|  |   ver_1 = (z0 == 'z' && z1 == 'z' && !strcasecmp(cname+4,nerd_ver1)); | ||||||
|  |   ver_2 = (is_addr(ccopy,&dot_4) && !strcasecmp(dot_4,nerd_ver2)); | ||||||
|  |  | ||||||
|  |   if (ver_1) | ||||||
|  |     { | ||||||
|  |       const char *dot = strchr(cname, '.'); | ||||||
|  |       if ((z0 != 'z' && z1 != 'z') || dot != cname+4) | ||||||
|  |         { | ||||||
|  |           printf("Unexpected CNAME %s (ver_1)\n", cname); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |   else if (ver_2) | ||||||
|  |     { | ||||||
|  |       z0 = tolower(dot_4[1]); | ||||||
|  |       z1 = tolower(dot_4[2]); | ||||||
|  |       if (z0 != 'z' && z1 != 'z') | ||||||
|  |         { | ||||||
|  |           printf("Unexpected CNAME %s (ver_2)\n", cname); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       printf("Unexpected CNAME %s (ver?)\n", cname); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   if (ver_1) | ||||||
|  |     { | ||||||
|  |       ccode_A2[0] = tolower(cname[2]); | ||||||
|  |       ccode_A2[1] = tolower(cname[3]); | ||||||
|  |       ccode_A2[2] = '\0'; | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     ccode_A2[0] = '\0'; | ||||||
|  |  | ||||||
|  |   cnumber = ip & 0xFFFF; | ||||||
|  |  | ||||||
|  |   TRACE(("Found country-code `%s', number %d\n", | ||||||
|  |          ver_1 ? ccode_A2 : "<n/a>", cnumber)); | ||||||
|  |  | ||||||
|  |   country = list_lookup(cnumber, country_list, | ||||||
|  |                         sizeof(country_list) / sizeof(country_list[0])); | ||||||
|  |   if (!country) | ||||||
|  |     printf("Name for country-number %d not found.\n", cnumber); | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       if (ver_1 && *(unsigned short*)&country->short_name != *(unsigned*)&ccode_A2) | ||||||
|  |         printf("short-name mismatch; %s vs %s\n", country->short_name, ccode_A2); | ||||||
|  |  | ||||||
|  |       printf("%s (%s), number %d.\n", | ||||||
|  |              country->long_name, country->short_name, cnumber); | ||||||
|  |     } | ||||||
|  |   free(ccopy); | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -40,13 +40,6 @@ | |||||||
| #include "inet_net_pton.h" | #include "inet_net_pton.h" | ||||||
| #include "ares_getopt.h" | #include "ares_getopt.h" | ||||||
|  |  | ||||||
| #ifndef HAVE_STRUCT_IN6_ADDR |  | ||||||
| struct in6_addr |  | ||||||
| { |  | ||||||
|   unsigned char s6_addr[16]; |  | ||||||
| }; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static void callback(void *arg, int status, int timeouts, struct hostent *host); | static void callback(void *arg, int status, int timeouts, struct hostent *host); | ||||||
| static void usage(void); | static void usage(void); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								ares/ares.h
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								ares/ares.h
									
									
									
									
									
								
							| @@ -18,6 +18,14 @@ | |||||||
| #ifndef ARES__H | #ifndef ARES__H | ||||||
| #define ARES__H | #define ARES__H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Define WIN32 when build target is Win32 API | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) | ||||||
|  | #define WIN32 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  |  | ||||||
| #if defined(_AIX) || (defined(NETWARE) && defined(__NOVELL_LIBC__)) | #if defined(_AIX) || (defined(NETWARE) && defined(__NOVELL_LIBC__)) | ||||||
| @@ -35,8 +43,12 @@ | |||||||
|   #include <sys/socket.h> |   #include <sys/socket.h> | ||||||
|   #include <tcp.h> |   #include <tcp.h> | ||||||
| #elif defined(WIN32) | #elif defined(WIN32) | ||||||
|   #include <winsock2.h> | #  ifndef WIN32_LEAN_AND_MEAN | ||||||
|  | #    define WIN32_LEAN_AND_MEAN | ||||||
|  | #  endif | ||||||
| #  include <windows.h> | #  include <windows.h> | ||||||
|  | #  include <winsock2.h> | ||||||
|  | #  include <ws2tcpip.h> | ||||||
| #else | #else | ||||||
|   #include <netinet/in.h> |   #include <netinet/in.h> | ||||||
|   #include <sys/socket.h> |   #include <sys/socket.h> | ||||||
| @@ -232,10 +244,38 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, | |||||||
|                      int alen, char **s, long *enclen); |                      int alen, char **s, long *enclen); | ||||||
| int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf, | int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf, | ||||||
|                      int alen, unsigned char **s, long *enclen); |                      int alen, unsigned char **s, long *enclen); | ||||||
|  |  | ||||||
|  | #if !defined(HAVE_STRUCT_IN6_ADDR) && !defined(s6_addr) | ||||||
|  | struct in6_addr { | ||||||
|  |   union { | ||||||
|  |     unsigned char _S6_u8[16]; | ||||||
|  |   } _S6_un; | ||||||
|  | }; | ||||||
|  | #define s6_addr _S6_un._S6_u8 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct addrttl { | ||||||
|  |   struct in_addr ipaddr; | ||||||
|  |   int            ttl; | ||||||
|  | }; | ||||||
|  | struct addr6ttl { | ||||||
|  |   struct in6_addr ip6addr; | ||||||
|  |   int             ttl; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | ** Parse the buffer, starting at *abuf and of length alen bytes, previously | ||||||
|  | ** obtained from an ares_search call.  Put the results in *host, if nonnull. | ||||||
|  | ** Also, if addrttls is nonnull, put up to *naddrttls IPv4 addresses along with | ||||||
|  | ** their TTLs in that array, and set *naddrttls to the number of addresses | ||||||
|  | ** so written. | ||||||
|  | */ | ||||||
| int ares_parse_a_reply(const unsigned char *abuf, int alen, | int ares_parse_a_reply(const unsigned char *abuf, int alen, | ||||||
|                        struct hostent **host); |                        struct hostent **host, | ||||||
|  |                        struct addrttl *addrttls, int *naddrttls); | ||||||
| int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | ||||||
|                        struct hostent **host); |                        struct hostent **host, | ||||||
|  |                        struct addr6ttl *addrttls, int *naddrttls); | ||||||
| int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, | int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, | ||||||
|                          int addrlen, int family, struct hostent **host); |                          int addrlen, int family, struct hostent **host); | ||||||
| int ares_parse_ns_reply(const unsigned char *abuf, int alen, | int ares_parse_ns_reply(const unsigned char *abuf, int alen, | ||||||
|   | |||||||
| @@ -58,6 +58,7 @@ static void addr_callback(void *arg, int status, int timeouts, | |||||||
| static void end_aquery(struct addr_query *aquery, int status, | static void end_aquery(struct addr_query *aquery, int status, | ||||||
|                        struct hostent *host); |                        struct hostent *host); | ||||||
| static int file_lookup(union ares_addr *addr, int family, struct hostent **host); | static int file_lookup(union ares_addr *addr, int family, struct hostent **host); | ||||||
|  | static void ptr_rr_name(char *name, int family, union ares_addr *addr); | ||||||
|  |  | ||||||
| void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, | void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, | ||||||
|                         int family, ares_host_callback callback, void *arg) |                         int family, ares_host_callback callback, void *arg) | ||||||
| @@ -101,48 +102,26 @@ static void next_lookup(struct addr_query *aquery) | |||||||
| { | { | ||||||
|   const char *p; |   const char *p; | ||||||
|   char name[128]; |   char name[128]; | ||||||
|   int a1, a2, a3, a4, status; |   int status; | ||||||
|   struct hostent *host; |   struct hostent *host; | ||||||
|   unsigned long addr; |  | ||||||
|  |  | ||||||
|   for (p = aquery->remaining_lookups; *p; p++) |   for (p = aquery->remaining_lookups; *p; p++) | ||||||
|     { |     { | ||||||
|       switch (*p) |       switch (*p) | ||||||
|         { |         { | ||||||
|         case 'b': |         case 'b': | ||||||
|           if (aquery->family == AF_INET) |           ptr_rr_name(name, aquery->family, &aquery->addr); | ||||||
|             { |  | ||||||
|               addr = ntohl(aquery->addr.addr4.s_addr); |  | ||||||
|               a1 = (int)((addr >> 24) & 0xff); |  | ||||||
|               a2 = (int)((addr >> 16) & 0xff); |  | ||||||
|               a3 = (int)((addr >> 8) & 0xff); |  | ||||||
|               a4 = (int)(addr & 0xff); |  | ||||||
|               sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1); |  | ||||||
|           aquery->remaining_lookups = p + 1; |           aquery->remaining_lookups = p + 1; | ||||||
|           ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, |           ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, | ||||||
|                      aquery); |                      aquery); | ||||||
|             } |  | ||||||
|           else |  | ||||||
|             { |  | ||||||
|               unsigned char *bytes; |  | ||||||
|               bytes = (unsigned char *)&aquery->addr.addr6.s6_addr; |  | ||||||
|               sprintf(name, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", |  | ||||||
|                       bytes[15]&0xf, bytes[15] >> 4, bytes[14]&0xf, bytes[14] >> 4, |  | ||||||
|                       bytes[13]&0xf, bytes[13] >> 4, bytes[12]&0xf, bytes[12] >> 4, |  | ||||||
|                       bytes[11]&0xf, bytes[11] >> 4, bytes[10]&0xf, bytes[10] >> 4, |  | ||||||
|                       bytes[9]&0xf, bytes[9] >> 4, bytes[8]&0xf, bytes[8] >> 4, |  | ||||||
|                       bytes[7]&0xf, bytes[7] >> 4, bytes[6]&0xf, bytes[6] >> 4, |  | ||||||
|                       bytes[5]&0xf, bytes[5] >> 4, bytes[4]&0xf, bytes[4] >> 4, |  | ||||||
|                       bytes[3]&0xf, bytes[3] >> 4, bytes[2]&0xf, bytes[2] >> 4, |  | ||||||
|                       bytes[1]&0xf, bytes[1] >> 4, bytes[0]&0xf, bytes[0] >> 4); |  | ||||||
|               aquery->remaining_lookups = p + 1; |  | ||||||
|               ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, |  | ||||||
|                          aquery); |  | ||||||
|             } |  | ||||||
|           return; |           return; | ||||||
|         case 'f': |         case 'f': | ||||||
|           status = file_lookup(&aquery->addr, aquery->family, &host); |           status = file_lookup(&aquery->addr, aquery->family, &host); | ||||||
|           if (status != ARES_ENOTFOUND) |  | ||||||
|  |           /* this status check below previously checked for !ARES_ENOTFOUND, | ||||||
|  |              but we should not assume that this single error code is the one | ||||||
|  |              that can occur, as that is in fact no longer the case */ | ||||||
|  |           if (status == ARES_SUCCESS) | ||||||
|             { |             { | ||||||
|               end_aquery(aquery, status, host); |               end_aquery(aquery, status, host); | ||||||
|               return; |               return; | ||||||
| @@ -264,3 +243,31 @@ static int file_lookup(union ares_addr *addr, int family, struct hostent **host) | |||||||
|     *host = NULL; |     *host = NULL; | ||||||
|   return status; |   return status; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void ptr_rr_name(char *name, int family, union ares_addr *addr) | ||||||
|  | { | ||||||
|  |   if (family == AF_INET) | ||||||
|  |     { | ||||||
|  |        unsigned long laddr = ntohl(addr->addr4.s_addr); | ||||||
|  |        int a1 = (int)((laddr >> 24) & 0xff); | ||||||
|  |        int a2 = (int)((laddr >> 16) & 0xff); | ||||||
|  |        int a3 = (int)((laddr >> 8) & 0xff); | ||||||
|  |        int a4 = (int)(laddr & 0xff); | ||||||
|  |        sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1); | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |        unsigned char *bytes = (unsigned char *)&addr->addr6.s6_addr; | ||||||
|  |        sprintf(name, | ||||||
|  |                 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." | ||||||
|  |                 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", | ||||||
|  |                 bytes[15]&0xf, bytes[15] >> 4, bytes[14]&0xf, bytes[14] >> 4, | ||||||
|  |                 bytes[13]&0xf, bytes[13] >> 4, bytes[12]&0xf, bytes[12] >> 4, | ||||||
|  |                 bytes[11]&0xf, bytes[11] >> 4, bytes[10]&0xf, bytes[10] >> 4, | ||||||
|  |                 bytes[9]&0xf, bytes[9] >> 4, bytes[8]&0xf, bytes[8] >> 4, | ||||||
|  |                 bytes[7]&0xf, bytes[7] >> 4, bytes[6]&0xf, bytes[6] >> 4, | ||||||
|  |                 bytes[5]&0xf, bytes[5] >> 4, bytes[4]&0xf, bytes[4] >> 4, | ||||||
|  |                 bytes[3]&0xf, bytes[3] >> 4, bytes[2]&0xf, bytes[2] >> 4, | ||||||
|  |                 bytes[1]&0xf, bytes[1] >> 4, bytes[0]&0xf, bytes[0] >> 4); | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ struct host_query { | |||||||
|   int timeouts; |   int timeouts; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void next_lookup(struct host_query *hquery, int status); | static void next_lookup(struct host_query *hquery, int status_code); | ||||||
| static void host_callback(void *arg, int status, int timeouts, | static void host_callback(void *arg, int status, int timeouts, | ||||||
|                           unsigned char *abuf, int alen); |                           unsigned char *abuf, int alen); | ||||||
| static void end_hquery(struct host_query *hquery, int status, | static void end_hquery(struct host_query *hquery, int status, | ||||||
| @@ -111,13 +111,14 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family, | |||||||
|   hquery->timeouts = 0; |   hquery->timeouts = 0; | ||||||
|  |  | ||||||
|   /* Start performing lookups according to channel->lookups. */ |   /* Start performing lookups according to channel->lookups. */ | ||||||
|   next_lookup(hquery, ARES_SUCCESS); |   next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void next_lookup(struct host_query *hquery, int status) | static void next_lookup(struct host_query *hquery, int status_code) | ||||||
| { | { | ||||||
|   const char *p; |   const char *p; | ||||||
|   struct hostent *host; |   struct hostent *host; | ||||||
|  |   int status = status_code; | ||||||
|  |  | ||||||
|   for (p = hquery->remaining_lookups; *p; p++) |   for (p = hquery->remaining_lookups; *p; p++) | ||||||
|     { |     { | ||||||
| @@ -137,11 +138,16 @@ static void next_lookup(struct host_query *hquery, int status) | |||||||
|         case 'f': |         case 'f': | ||||||
|           /* Host file lookup */ |           /* Host file lookup */ | ||||||
|           status = file_lookup(hquery->name, hquery->family, &host); |           status = file_lookup(hquery->name, hquery->family, &host); | ||||||
|           if (status != ARES_ENOTFOUND) |  | ||||||
|  |           /* this status check below previously checked for !ARES_ENOTFOUND, | ||||||
|  |              but we should not assume that this single error code is the one | ||||||
|  |              that can occur, as that is in fact no longer the case */ | ||||||
|  |           if (status == ARES_SUCCESS) | ||||||
|             { |             { | ||||||
|               end_hquery(hquery, status, host); |               end_hquery(hquery, status, host); | ||||||
|               return; |               return; | ||||||
|             } |             } | ||||||
|  |           status = status_code;   /* Use original status code */ | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -160,13 +166,13 @@ static void host_callback(void *arg, int status, int timeouts, | |||||||
|     { |     { | ||||||
|       if (hquery->family == AF_INET) |       if (hquery->family == AF_INET) | ||||||
|         { |         { | ||||||
|           status = ares_parse_a_reply(abuf, alen, &host); |           status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL); | ||||||
|           if (host && channel->nsort) |           if (host && channel->nsort) | ||||||
|             sort_addresses(host, channel->sortlist, channel->nsort); |             sort_addresses(host, channel->sortlist, channel->nsort); | ||||||
|         } |         } | ||||||
|       else if (hquery->family == AF_INET6) |       else if (hquery->family == AF_INET6) | ||||||
|         { |         { | ||||||
|           status = ares_parse_aaaa_reply(abuf, alen, &host); |           status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL); | ||||||
|           if (host && channel->nsort) |           if (host && channel->nsort) | ||||||
|             sort6_addresses(host, channel->sortlist, channel->nsort); |             sort6_addresses(host, channel->sortlist, channel->nsort); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| /* $Id$ */ | /* $Id$ */ | ||||||
|  |  | ||||||
| /* | /* Copyright (C) 2005 by Dominick Meglio | ||||||
|  |  * | ||||||
|  * Permission to use, copy, modify, and distribute this |  * Permission to use, copy, modify, and distribute this | ||||||
|  * software and its documentation for any purpose and without |  * software and its documentation for any purpose and without | ||||||
|  * fee is hereby granted, provided that the above copyright |  * fee is hereby granted, provided that the above copyright | ||||||
| @@ -21,11 +22,13 @@ | |||||||
| #define PF_INET6 AF_INET6 | #define PF_INET6 AF_INET6 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef HAVE_STRUCT_IN6_ADDR | #if !defined(HAVE_STRUCT_IN6_ADDR) && !defined(s6_addr) | ||||||
| struct in6_addr | struct in6_addr { | ||||||
| { |   union { | ||||||
|   unsigned char s6_addr[16]; |     unsigned char _S6_u8[16]; | ||||||
|  |   } _S6_un; | ||||||
| }; | }; | ||||||
|  | #define s6_addr _S6_un._S6_u8 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef HAVE_STRUCT_SOCKADDR_IN6 | #ifndef HAVE_STRUCT_SOCKADDR_IN6 | ||||||
|   | |||||||
| @@ -22,24 +22,39 @@ ares_parse_a_reply \- Parse a reply to a DNS query of type A into a hostent | |||||||
| .B #include <ares.h> | .B #include <ares.h> | ||||||
| .PP | .PP | ||||||
| .B int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, | .B int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, | ||||||
| .B 	struct hostent **\fIhost\fP); | .B 	struct hostent **\fIhost\fP, | ||||||
|  | .B      struct addrttl *\fIaddrttls\fB, int *\fInaddrttls\fB); | ||||||
| .fi | .fi | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| The | The | ||||||
| .B ares_parse_a_reply | .B ares_parse_a_reply | ||||||
| function parses the response to a query of type A into a | function parses the response to a query of type A into a | ||||||
| .BR "struct hostent" . | .BR "struct hostent" | ||||||
|  | and/or an array of | ||||||
|  | .BR "struct addrttls" .  | ||||||
| The parameters | The parameters | ||||||
| .I abuf | .I abuf | ||||||
| and | and | ||||||
| .I alen | .I alen | ||||||
| give the contents of the response.  The result is stored in allocated | give the contents of the response.  The result is stored in allocated | ||||||
| memory and a pointer to it stored into the variable pointed to by | memory and a pointer to it stored into the variable pointed to by | ||||||
| .IR host . | .IR host , | ||||||
|  | if host is nonnull. | ||||||
| It is the caller's responsibility to free the resulting host structure | It is the caller's responsibility to free the resulting host structure | ||||||
| using | using | ||||||
| .BR ares_free_hostent (3) | .BR ares_free_hostent (3) | ||||||
| when it is no longer needed. | when it is no longer needed. | ||||||
|  | .PP | ||||||
|  | If | ||||||
|  | .IR addrttls | ||||||
|  | and | ||||||
|  | .IR naddrttls | ||||||
|  | are both nonnull, | ||||||
|  | then up to *naddrttls | ||||||
|  | .BR "struct addrttl" | ||||||
|  | records are stored in the array pointed to by addrttls, | ||||||
|  | and then *naddrttls is set to the number of records so stored. | ||||||
|  | Note that the memory for these records is supplied by the caller. | ||||||
| .SH RETURN VALUES | .SH RETURN VALUES | ||||||
| .B ares_parse_a_reply | .B ares_parse_a_reply | ||||||
| can return any of the following values: | can return any of the following values: | ||||||
|   | |||||||
| @@ -32,24 +32,32 @@ | |||||||
|  |  | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <limits.h> | ||||||
| #include "ares.h" | #include "ares.h" | ||||||
| #include "ares_dns.h" | #include "ares_dns.h" | ||||||
| #include "ares_private.h" | #include "ares_private.h" | ||||||
|  |  | ||||||
| int ares_parse_a_reply(const unsigned char *abuf, int alen, | int ares_parse_a_reply(const unsigned char *abuf, int alen, | ||||||
|                        struct hostent **host) |                        struct hostent **host, | ||||||
|  |                        struct addrttl *addrttls, int *naddrttls) | ||||||
| { | { | ||||||
|   unsigned int qdcount, ancount; |   unsigned int qdcount, ancount; | ||||||
|   int status, i, rr_type, rr_class, rr_len, naddrs; |   int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs; | ||||||
|  |   int cname_ttl = INT_MAX;  /* the TTL imposed by the CNAME chain */ | ||||||
|   int naliases; |   int naliases; | ||||||
|   long len; |   long len; | ||||||
|   const unsigned char *aptr; |   const unsigned char *aptr; | ||||||
|   char *hostname, *rr_name, *rr_data, **aliases; |   char *hostname, *rr_name, *rr_data, **aliases; | ||||||
|   struct in_addr *addrs; |   struct in_addr *addrs; | ||||||
|   struct hostent *hostent; |   struct hostent *hostent; | ||||||
|  |   const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0; | ||||||
|  |  | ||||||
|   /* Set *host to NULL for all failure cases. */ |   /* Set *host to NULL for all failure cases. */ | ||||||
|  |   if (host) | ||||||
|     *host = NULL; |     *host = NULL; | ||||||
|  |   /* Same with *naddrttls. */ | ||||||
|  |   if (naddrttls) | ||||||
|  |     *naddrttls = 0; | ||||||
|  |  | ||||||
|   /* Give up if abuf doesn't have room for a header. */ |   /* Give up if abuf doesn't have room for a header. */ | ||||||
|   if (alen < HFIXEDSZ) |   if (alen < HFIXEDSZ) | ||||||
| @@ -73,6 +81,8 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|     } |     } | ||||||
|   aptr += len + QFIXEDSZ; |   aptr += len + QFIXEDSZ; | ||||||
|  |  | ||||||
|  |   if (host) | ||||||
|  |     { | ||||||
|       /* Allocate addresses and aliases; ancount gives an upper bound for both. */ |       /* Allocate addresses and aliases; ancount gives an upper bound for both. */ | ||||||
|       addrs = malloc(ancount * sizeof(struct in_addr)); |       addrs = malloc(ancount * sizeof(struct in_addr)); | ||||||
|       if (!addrs) |       if (!addrs) | ||||||
| @@ -87,6 +97,13 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|           free(addrs); |           free(addrs); | ||||||
|           return ARES_ENOMEM; |           return ARES_ENOMEM; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       addrs = NULL; | ||||||
|  |       aliases = NULL; | ||||||
|  |     } | ||||||
|  |    | ||||||
|   naddrs = 0; |   naddrs = 0; | ||||||
|   naliases = 0; |   naliases = 0; | ||||||
|  |  | ||||||
| @@ -106,13 +123,33 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|       rr_type = DNS_RR_TYPE(aptr); |       rr_type = DNS_RR_TYPE(aptr); | ||||||
|       rr_class = DNS_RR_CLASS(aptr); |       rr_class = DNS_RR_CLASS(aptr); | ||||||
|       rr_len = DNS_RR_LEN(aptr); |       rr_len = DNS_RR_LEN(aptr); | ||||||
|  |       rr_ttl = DNS_RR_TTL(aptr); | ||||||
|       aptr += RRFIXEDSZ; |       aptr += RRFIXEDSZ; | ||||||
|  |  | ||||||
|       if (rr_class == C_IN && rr_type == T_A |       if (rr_class == C_IN && rr_type == T_A | ||||||
|           && rr_len == sizeof(struct in_addr) |           && rr_len == sizeof(struct in_addr) | ||||||
|           && strcasecmp(rr_name, hostname) == 0) |           && strcasecmp(rr_name, hostname) == 0) | ||||||
|         { |         { | ||||||
|  |           if (addrs) | ||||||
|  |             { | ||||||
|  |               if (aptr + sizeof(struct in_addr) > abuf + alen) | ||||||
|  |               { | ||||||
|  |                 status = ARES_EBADRESP; | ||||||
|  |                 break; | ||||||
|  |               } | ||||||
|               memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr)); |               memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr)); | ||||||
|  |             } | ||||||
|  |           if (naddrs < max_addr_ttls) | ||||||
|  |             { | ||||||
|  |               struct addrttl * const at = &addrttls[naddrs]; | ||||||
|  |               if (aptr + sizeof(struct in_addr) > abuf + alen) | ||||||
|  |               { | ||||||
|  |                 status = ARES_EBADRESP; | ||||||
|  |                 break; | ||||||
|  |               } | ||||||
|  |               memcpy(&at->ipaddr, aptr,  sizeof(struct in_addr)); | ||||||
|  |               at->ttl = rr_ttl; | ||||||
|  |             } | ||||||
|           naddrs++; |           naddrs++; | ||||||
|           status = ARES_SUCCESS; |           status = ARES_SUCCESS; | ||||||
|         } |         } | ||||||
| @@ -120,7 +157,10 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|       if (rr_class == C_IN && rr_type == T_CNAME) |       if (rr_class == C_IN && rr_type == T_CNAME) | ||||||
|         { |         { | ||||||
|           /* Record the RR name as an alias. */ |           /* Record the RR name as an alias. */ | ||||||
|  |           if (aliases) | ||||||
|             aliases[naliases] = rr_name; |             aliases[naliases] = rr_name; | ||||||
|  |           else | ||||||
|  |             free(rr_name); | ||||||
|           naliases++; |           naliases++; | ||||||
|  |  | ||||||
|           /* Decode the RR data and replace the hostname with it. */ |           /* Decode the RR data and replace the hostname with it. */ | ||||||
| @@ -129,6 +169,10 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|             break; |             break; | ||||||
|           free(hostname); |           free(hostname); | ||||||
|           hostname = rr_data; |           hostname = rr_data; | ||||||
|  |  | ||||||
|  |           /* Take the min of the TTLs we see in the CNAME chain. */ | ||||||
|  |           if (cname_ttl > rr_ttl) | ||||||
|  |             cname_ttl = rr_ttl; | ||||||
|         } |         } | ||||||
|       else |       else | ||||||
|         free(rr_name); |         free(rr_name); | ||||||
| @@ -145,8 +189,23 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|     status = ARES_ENODATA; |     status = ARES_ENODATA; | ||||||
|   if (status == ARES_SUCCESS) |   if (status == ARES_SUCCESS) | ||||||
|     { |     { | ||||||
|       /* We got our answer.  Allocate memory to build the host entry. */ |       /* We got our answer. */ | ||||||
|  |       if (naddrttls) | ||||||
|  |         { | ||||||
|  |           const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls; | ||||||
|  |           for (i = 0; i < n; i++) | ||||||
|  |             { | ||||||
|  |               /* Ensure that each A TTL is no larger than the CNAME TTL. */ | ||||||
|  |               if (addrttls[i].ttl > cname_ttl) | ||||||
|  |                 addrttls[i].ttl = cname_ttl; | ||||||
|  |             } | ||||||
|  |           *naddrttls = n; | ||||||
|  |         } | ||||||
|  |       if (aliases) | ||||||
|         aliases[naliases] = NULL; |         aliases[naliases] = NULL; | ||||||
|  |       if (host) | ||||||
|  |         { | ||||||
|  |           /* Allocate memory to build the host entry. */ | ||||||
|           hostent = malloc(sizeof(struct hostent)); |           hostent = malloc(sizeof(struct hostent)); | ||||||
|           if (hostent) |           if (hostent) | ||||||
|             { |             { | ||||||
| @@ -168,9 +227,13 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, | |||||||
|             } |             } | ||||||
|           status = ARES_ENOMEM; |           status = ARES_ENOMEM; | ||||||
|         } |         } | ||||||
|  |      } | ||||||
|  |   if (aliases) | ||||||
|  |     { | ||||||
|       for (i = 0; i < naliases; i++) |       for (i = 0; i < naliases; i++) | ||||||
|         free(aliases[i]); |         free(aliases[i]); | ||||||
|       free(aliases); |       free(aliases); | ||||||
|  |     } | ||||||
|   free(addrs); |   free(addrs); | ||||||
|   free(hostname); |   free(hostname); | ||||||
|   return status; |   return status; | ||||||
|   | |||||||
| @@ -22,24 +22,39 @@ ares_parse_aaaa_reply \- Parse a reply to a DNS query of type AAAA into a hosten | |||||||
| .B #include <ares.h> | .B #include <ares.h> | ||||||
| .PP | .PP | ||||||
| .B int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, | .B int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, | ||||||
| .B 	struct hostent **\fIhost\fP); | .B 	struct hostent **\fIhost\fP,          | ||||||
|  | .B      struct addrttl *\fIaddrttls\fB, int *\fInaddrttls\fB); | ||||||
| .fi | .fi | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| The | The | ||||||
| .B ares_parse_aaaa_reply | .B ares_parse_aaaa_reply | ||||||
| function parses the response to a query of type AAAA into a | function parses the response to a query of type AAAA into a | ||||||
| .BR "struct hostent" . | .BR "struct hostent" | ||||||
|  | and/or an array of | ||||||
|  | .BR "struct addrttls" .  | ||||||
| The parameters | The parameters | ||||||
| .I abuf | .I abuf | ||||||
| and | and | ||||||
| .I alen | .I alen | ||||||
| give the contents of the response.  The result is stored in allocated | give the contents of the response.  The result is stored in allocated | ||||||
| memory and a pointer to it stored into the variable pointed to by | memory and a pointer to it stored into the variable pointed to by | ||||||
| .IR host . | .IR host , | ||||||
|  | if host is nonnull. | ||||||
| It is the caller's responsibility to free the resulting host structure | It is the caller's responsibility to free the resulting host structure | ||||||
| using | using | ||||||
| .BR ares_free_hostent (3) | .BR ares_free_hostent (3) | ||||||
| when it is no longer needed. | when it is no longer needed. | ||||||
|  | .PP | ||||||
|  | If | ||||||
|  | .IR addrttls | ||||||
|  | and | ||||||
|  | .IR naddrttls | ||||||
|  | are both nonnull, | ||||||
|  | then up to *naddrttls | ||||||
|  | .BR "struct addr6ttl" | ||||||
|  | records are stored in the array pointed to by addrttls, | ||||||
|  | and then *naddrttls is set to the number of records so stored. | ||||||
|  | Note that the memory for these records is supplied by the caller. | ||||||
| .SH RETURN VALUES | .SH RETURN VALUES | ||||||
| .B ares_parse_aaaa_reply | .B ares_parse_aaaa_reply | ||||||
| can return any of the following values: | can return any of the following values: | ||||||
|   | |||||||
| @@ -34,25 +34,33 @@ | |||||||
|  |  | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <limits.h> | ||||||
| #include "ares.h" | #include "ares.h" | ||||||
| #include "ares_dns.h" | #include "ares_dns.h" | ||||||
| #include "inet_net_pton.h" | #include "inet_net_pton.h" | ||||||
| #include "ares_private.h" | #include "ares_private.h" | ||||||
|  |  | ||||||
| int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | ||||||
|                        struct hostent **host) |                           struct hostent **host, struct addr6ttl *addrttls, | ||||||
|  |                           int *naddrttls) | ||||||
| { | { | ||||||
|   unsigned int qdcount, ancount; |   unsigned int qdcount, ancount; | ||||||
|   int status, i, rr_type, rr_class, rr_len, naddrs; |   int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs; | ||||||
|  |   int cname_ttl = INT_MAX;  /* the TTL imposed by the CNAME chain */ | ||||||
|   int naliases; |   int naliases; | ||||||
|   long len; |   long len; | ||||||
|   const unsigned char *aptr; |   const unsigned char *aptr; | ||||||
|   char *hostname, *rr_name, *rr_data, **aliases; |   char *hostname, *rr_name, *rr_data, **aliases; | ||||||
|   struct in6_addr *addrs; |   struct in6_addr *addrs; | ||||||
|   struct hostent *hostent; |   struct hostent *hostent; | ||||||
|  |   const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0; | ||||||
|  |  | ||||||
|   /* Set *host to NULL for all failure cases. */ |   /* Set *host to NULL for all failure cases. */ | ||||||
|  |   if (host) | ||||||
|     *host = NULL; |     *host = NULL; | ||||||
|  |   /* Same with *naddrttls. */ | ||||||
|  |   if (naddrttls) | ||||||
|  |     *naddrttls = 0; | ||||||
|  |  | ||||||
|   /* Give up if abuf doesn't have room for a header. */ |   /* Give up if abuf doesn't have room for a header. */ | ||||||
|   if (alen < HFIXEDSZ) |   if (alen < HFIXEDSZ) | ||||||
| @@ -77,6 +85,8 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|   aptr += len + QFIXEDSZ; |   aptr += len + QFIXEDSZ; | ||||||
|  |  | ||||||
|   /* Allocate addresses and aliases; ancount gives an upper bound for both. */ |   /* Allocate addresses and aliases; ancount gives an upper bound for both. */ | ||||||
|  |   if (host) | ||||||
|  |     { | ||||||
|       addrs = malloc(ancount * sizeof(struct in6_addr)); |       addrs = malloc(ancount * sizeof(struct in6_addr)); | ||||||
|       if (!addrs) |       if (!addrs) | ||||||
|         { |         { | ||||||
| @@ -90,6 +100,12 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|           free(addrs); |           free(addrs); | ||||||
|           return ARES_ENOMEM; |           return ARES_ENOMEM; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       addrs = NULL; | ||||||
|  |       aliases = NULL; | ||||||
|  |     } | ||||||
|   naddrs = 0; |   naddrs = 0; | ||||||
|   naliases = 0; |   naliases = 0; | ||||||
|  |  | ||||||
| @@ -109,13 +125,33 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|       rr_type = DNS_RR_TYPE(aptr); |       rr_type = DNS_RR_TYPE(aptr); | ||||||
|       rr_class = DNS_RR_CLASS(aptr); |       rr_class = DNS_RR_CLASS(aptr); | ||||||
|       rr_len = DNS_RR_LEN(aptr); |       rr_len = DNS_RR_LEN(aptr); | ||||||
|  |       rr_ttl = DNS_RR_TTL(aptr); | ||||||
|       aptr += RRFIXEDSZ; |       aptr += RRFIXEDSZ; | ||||||
|  |  | ||||||
|       if (rr_class == C_IN && rr_type == T_AAAA |       if (rr_class == C_IN && rr_type == T_AAAA | ||||||
|           && rr_len == sizeof(struct in6_addr) |           && rr_len == sizeof(struct in6_addr) | ||||||
|           && strcasecmp(rr_name, hostname) == 0) |           && strcasecmp(rr_name, hostname) == 0) | ||||||
|         { |         { | ||||||
|  |           if (addrs) | ||||||
|  |             { | ||||||
|  |               if (aptr + sizeof(struct in6_addr) > abuf + alen) | ||||||
|  |               { | ||||||
|  |                 status = ARES_EBADRESP; | ||||||
|  |                 break; | ||||||
|  |               } | ||||||
|               memcpy(&addrs[naddrs], aptr, sizeof(struct in6_addr)); |               memcpy(&addrs[naddrs], aptr, sizeof(struct in6_addr)); | ||||||
|  |             } | ||||||
|  |           if (naddrs < max_addr_ttls) | ||||||
|  |             { | ||||||
|  |               struct addr6ttl * const at = &addrttls[naddrs]; | ||||||
|  |               if (aptr + sizeof(struct in6_addr) > abuf + alen) | ||||||
|  |               { | ||||||
|  |                 status = ARES_EBADRESP; | ||||||
|  |                 break; | ||||||
|  |               } | ||||||
|  |               memcpy(&at->ip6addr, aptr,  sizeof(struct in6_addr)); | ||||||
|  |               at->ttl = rr_ttl; | ||||||
|  |             } | ||||||
|           naddrs++; |           naddrs++; | ||||||
|           status = ARES_SUCCESS; |           status = ARES_SUCCESS; | ||||||
|         } |         } | ||||||
| @@ -123,7 +159,10 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|       if (rr_class == C_IN && rr_type == T_CNAME) |       if (rr_class == C_IN && rr_type == T_CNAME) | ||||||
|         { |         { | ||||||
|           /* Record the RR name as an alias. */ |           /* Record the RR name as an alias. */ | ||||||
|  |           if (aliases) | ||||||
|             aliases[naliases] = rr_name; |             aliases[naliases] = rr_name; | ||||||
|  |           else | ||||||
|  |             free(rr_name); | ||||||
|           naliases++; |           naliases++; | ||||||
|  |  | ||||||
|           /* Decode the RR data and replace the hostname with it. */ |           /* Decode the RR data and replace the hostname with it. */ | ||||||
| @@ -132,6 +171,10 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|             break; |             break; | ||||||
|           free(hostname); |           free(hostname); | ||||||
|           hostname = rr_data; |           hostname = rr_data; | ||||||
|  |  | ||||||
|  |           /* Take the min of the TTLs we see in the CNAME chain. */ | ||||||
|  |           if (cname_ttl > rr_ttl) | ||||||
|  |             cname_ttl = rr_ttl; | ||||||
|         } |         } | ||||||
|       else |       else | ||||||
|         free(rr_name); |         free(rr_name); | ||||||
| @@ -148,8 +191,23 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|     status = ARES_ENODATA; |     status = ARES_ENODATA; | ||||||
|   if (status == ARES_SUCCESS) |   if (status == ARES_SUCCESS) | ||||||
|     { |     { | ||||||
|       /* We got our answer.  Allocate memory to build the host entry. */ |       /* We got our answer. */ | ||||||
|  |       if (naddrttls) | ||||||
|  |         { | ||||||
|  |           const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls; | ||||||
|  |           for (i = 0; i < n; i++) | ||||||
|  |             { | ||||||
|  |               /* Ensure that each A TTL is no larger than the CNAME TTL. */ | ||||||
|  |               if (addrttls[i].ttl > cname_ttl) | ||||||
|  |                 addrttls[i].ttl = cname_ttl; | ||||||
|  |             } | ||||||
|  |           *naddrttls = n; | ||||||
|  |         } | ||||||
|  |       if (aliases) | ||||||
|         aliases[naliases] = NULL; |         aliases[naliases] = NULL; | ||||||
|  |       if (host) | ||||||
|  |         { | ||||||
|  |           /* Allocate memory to build the host entry. */ | ||||||
|           hostent = malloc(sizeof(struct hostent)); |           hostent = malloc(sizeof(struct hostent)); | ||||||
|           if (hostent) |           if (hostent) | ||||||
|             { |             { | ||||||
| @@ -171,9 +229,13 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, | |||||||
|             } |             } | ||||||
|           status = ARES_ENOMEM; |           status = ARES_ENOMEM; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |   if (aliases) | ||||||
|  |     { | ||||||
|       for (i = 0; i < naliases; i++) |       for (i = 0; i < naliases; i++) | ||||||
|         free(aliases[i]); |         free(aliases[i]); | ||||||
|       free(aliases); |       free(aliases); | ||||||
|  |     } | ||||||
|   free(addrs); |   free(addrs); | ||||||
|   free(hostname); |   free(hostname); | ||||||
|   return status; |   return status; | ||||||
|   | |||||||
| @@ -18,6 +18,14 @@ | |||||||
|  * without express or implied warranty. |  * without express or implied warranty. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Define WIN32 when build target is Win32 API | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) | ||||||
|  | #define WIN32 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,11 +5,11 @@ | |||||||
|  |  | ||||||
| #define ARES_VERSION_MAJOR 1 | #define ARES_VERSION_MAJOR 1 | ||||||
| #define ARES_VERSION_MINOR 5 | #define ARES_VERSION_MINOR 5 | ||||||
| #define ARES_VERSION_PATCH 0 | #define ARES_VERSION_PATCH 2 | ||||||
| #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ | #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ | ||||||
|                        (ARES_VERSION_MINOR<<8)|\ |                        (ARES_VERSION_MINOR<<8)|\ | ||||||
|                        (ARES_VERSION_PATCH)) |                        (ARES_VERSION_PATCH)) | ||||||
| #define ARES_VERSION_STR "1.5.0-CVS" | #define ARES_VERSION_STR "1.5.2-CVS" | ||||||
|  |  | ||||||
| #ifdef  __cplusplus | #ifdef  __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ | |||||||
|  |  | ||||||
| /* $Id$ */ | /* $Id$ */ | ||||||
|  |  | ||||||
| /* | /* Copyright (C) 2005 by Dominick Meglio | ||||||
|  |  * | ||||||
|  * Permission to use, copy, modify, and distribute this |  * Permission to use, copy, modify, and distribute this | ||||||
|  * software and its documentation for any purpose and without |  * software and its documentation for any purpose and without | ||||||
|  * fee is hereby granted, provided that the above copyright |  * fee is hereby granted, provided that the above copyright | ||||||
|   | |||||||
| @@ -159,24 +159,58 @@ | |||||||
| /* Define this if you have struct timeval */ | /* Define this if you have struct timeval */ | ||||||
| #define HAVE_STRUCT_TIMEVAL 1 | #define HAVE_STRUCT_TIMEVAL 1 | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------- */ | ||||||
|  | /*                        COMPILER SPECIFIC                         */ | ||||||
|  | /* ---------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | /* Define to avoid VS2005 complaining about portable C functions */ | ||||||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1400) | ||||||
|  | #define _CRT_SECURE_NO_DEPRECATE 1 | ||||||
|  | #define _CRT_NONSTDC_NO_DEPRECATE 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* VS2008 does not support Windows build targets prior to WinXP, */ | ||||||
|  | /* so, if no build target has been defined we will target WinXP. */ | ||||||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1500) | ||||||
|  | #  ifndef _WIN32_WINNT | ||||||
|  | #    define _WIN32_WINNT 0x0501 | ||||||
|  | #  endif | ||||||
|  | #  ifndef WINVER | ||||||
|  | #    define WINVER 0x0501 | ||||||
|  | #  endif | ||||||
|  | #  if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501) | ||||||
|  | #    error VS2008 does not support Windows build targets prior to WinXP | ||||||
|  | #  endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| /*                         IPV6 COMPATIBILITY                       */ | /*                         IPV6 COMPATIBILITY                       */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| /* Define this if you have address family AF_INET6 */ | /* Define this if you have address family AF_INET6 */ | ||||||
|  | #ifdef HAVE_WINSOCK2_H | ||||||
| #define HAVE_AF_INET6 1 | #define HAVE_AF_INET6 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Define this if you have protocol family PF_INET6 */ | /* Define this if you have protocol family PF_INET6 */ | ||||||
|  | #ifdef HAVE_WINSOCK2_H | ||||||
| #define HAVE_PF_INET6 1 | #define HAVE_PF_INET6 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Define this if you have struct in6_addr */ | /* Define this if you have struct in6_addr */ | ||||||
|  | #ifdef HAVE_WS2TCPIP_H | ||||||
| #define HAVE_STRUCT_IN6_ADDR 1 | #define HAVE_STRUCT_IN6_ADDR 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Define this if you have struct sockaddr_in6 */ | /* Define this if you have struct sockaddr_in6 */ | ||||||
|  | #ifdef HAVE_WS2TCPIP_H | ||||||
| #define HAVE_STRUCT_SOCKADDR_IN6 1 | #define HAVE_STRUCT_SOCKADDR_IN6 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Define this if you have sockaddr_in6 with scopeid */ | /* Define this if you have sockaddr_in6 with scopeid */ | ||||||
|  | #ifdef HAVE_WS2TCPIP_H | ||||||
| #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 | #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif  /* __ARES_CONFIG_WIN32_H */ | #endif  /* __ARES_CONFIG_WIN32_H */ | ||||||
|   | |||||||
| @@ -46,6 +46,8 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]), | |||||||
|     dnl when doing the debug stuff, use static library only |     dnl when doing the debug stuff, use static library only | ||||||
|     AC_DISABLE_SHARED |     AC_DISABLE_SHARED | ||||||
|  |  | ||||||
|  |     debugbuild="yes" | ||||||
|  |  | ||||||
|     dnl the entire --enable-debug is a hack that lives and runs on top of |     dnl the entire --enable-debug is a hack that lives and runs on top of | ||||||
|     dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier |     dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier | ||||||
|     AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl]) |     AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl]) | ||||||
| @@ -70,6 +72,7 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]), | |||||||
|   esac ], |   esac ], | ||||||
|        AC_MSG_RESULT(no) |        AC_MSG_RESULT(no) | ||||||
| ) | ) | ||||||
|  | AM_CONDITIONAL(DEBUGBUILD, test x$debugbuild = xyes) | ||||||
|  |  | ||||||
| dnl skip libtool C++ and Fortran compiler checks | dnl skip libtool C++ and Fortran compiler checks | ||||||
| m4_ifdef([AC_PROG_CXX], [m4_undefine([AC_PROG_CXX])]) | m4_ifdef([AC_PROG_CXX], [m4_undefine([AC_PROG_CXX])]) | ||||||
| @@ -258,9 +261,6 @@ fi | |||||||
| dnl socket lib? | dnl socket lib? | ||||||
| AC_CHECK_FUNC(connect, , [ AC_CHECK_LIB(socket, connect) ]) | AC_CHECK_FUNC(connect, , [ AC_CHECK_LIB(socket, connect) ]) | ||||||
|  |  | ||||||
| dnl dl lib? |  | ||||||
| AC_CHECK_FUNC(dlclose, , [ AC_CHECK_LIB(dl, dlopen) ]) |  | ||||||
|  |  | ||||||
| AC_MSG_CHECKING([whether to use libgcc]) | AC_MSG_CHECKING([whether to use libgcc]) | ||||||
| AC_ARG_ENABLE(libgcc, | AC_ARG_ENABLE(libgcc, | ||||||
| AC_HELP_STRING([--enable-libgcc],[use libgcc when linking]), | AC_HELP_STRING([--enable-libgcc],[use libgcc when linking]), | ||||||
| @@ -831,8 +831,15 @@ AC_HELP_STRING([--with-random=FILE], | |||||||
|                [read randomness from FILE (default=/dev/urandom)]), |                [read randomness from FILE (default=/dev/urandom)]), | ||||||
|     [ RANDOM_FILE="$withval" ], |     [ RANDOM_FILE="$withval" ], | ||||||
|     [ |     [ | ||||||
|         dnl Check for random device |         dnl Check for random device.  If we're cross compiling, we can't | ||||||
|  |         dnl check, and it's better to assume it doesn't exist than it is | ||||||
|  |         dnl to fail on AC_CHECK_FILE or later. | ||||||
|  |         if test "$cross_compiling" = "no"; then | ||||||
|           AC_CHECK_FILE("/dev/urandom", [ RANDOM_FILE="/dev/urandom"] ) |           AC_CHECK_FILE("/dev/urandom", [ RANDOM_FILE="/dev/urandom"] ) | ||||||
|  |         else | ||||||
|  |           AC_MSG_WARN([cannot check for /dev/urandom while cross compiling; assuming none]) | ||||||
|  |         fi | ||||||
|  |          | ||||||
|     ] |     ] | ||||||
| ) | ) | ||||||
| if test -n "$RANDOM_FILE" && test X"$RANDOM_FILE" != Xno ; then | if test -n "$RANDOM_FILE" && test X"$RANDOM_FILE" != Xno ; then | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ | |||||||
|  |  | ||||||
| /* $Id$ */ | /* $Id$ */ | ||||||
|  |  | ||||||
| /* | /* Copyright (C) 2005 by Daniel Stenberg | ||||||
|  |  * | ||||||
|  * Permission to use, copy, modify, and distribute this |  * Permission to use, copy, modify, and distribute this | ||||||
|  * software and its documentation for any purpose and without |  * software and its documentation for any purpose and without | ||||||
|  * fee is hereby granted, provided that the above copyright |  * fee is hereby granted, provided that the above copyright | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ | |||||||
|  |  | ||||||
| /* $Id$ */ | /* $Id$ */ | ||||||
|  |  | ||||||
| /* | /* Copyright (C) 2005 by Dominick Meglio | ||||||
|  |  * | ||||||
|  * Permission to use, copy, modify, and distribute this |  * Permission to use, copy, modify, and distribute this | ||||||
|  * software and its documentation for any purpose and without |  * software and its documentation for any purpose and without | ||||||
|  * fee is hereby granted, provided that the above copyright |  * fee is hereby granted, provided that the above copyright | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ includedir=@includedir@ | |||||||
|  |  | ||||||
| Name: c-ares | Name: c-ares | ||||||
| URL: http://daniel.haxx.se/projects/c-ares/ | URL: http://daniel.haxx.se/projects/c-ares/ | ||||||
| Description: asyncronous DNS lookup library | Description: asynchronous DNS lookup library | ||||||
| Version: @VERSION@ | Version: @VERSION@ | ||||||
| Requires:  | Requires:  | ||||||
| Requires.private:  | Requires.private:  | ||||||
|   | |||||||
| @@ -7,9 +7,6 @@ | |||||||
|    port build */ |    port build */ | ||||||
|  |  | ||||||
| #ifndef NETWARE | #ifndef NETWARE | ||||||
| #ifndef __CYGWIN__ |  | ||||||
| #include <windows.h> |  | ||||||
| #endif |  | ||||||
| #include <process.h> /* for the _getpid() proto */ | #include <process.h> /* for the _getpid() proto */ | ||||||
| #endif  /* !NETWARE */ | #endif  /* !NETWARE */ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								ares/setup.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								ares/setup.h
									
									
									
									
									
								
							| @@ -16,13 +16,11 @@ | |||||||
|  * without express or implied warranty. |  * without express or implied warranty. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #if !defined(WIN32) && defined(__WIN32__) | /* | ||||||
| /* Borland fix */ |  * Define WIN32 when build target is Win32 API | ||||||
| #define WIN32 |  */ | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if !defined(WIN32) && defined(_WIN32) | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) | ||||||
| /* VS2005 on x64 fix */ |  | ||||||
| #define WIN32 | #define WIN32 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,8 +49,8 @@ BSC32=bscmake.exe | |||||||
| # ADD BASE BSC32 /nologo | # ADD BASE BSC32 /nologo | ||||||
| # ADD BSC32 /nologo | # ADD BSC32 /nologo | ||||||
| LINK32=link.exe | LINK32=link.exe | ||||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | # ADD BASE LINK32 ws2_32.lib advapi32.lib /nologo /subsystem:console /machine:I386 | ||||||
| # ADD LINK32 wsock32.lib areslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\areslib\Release" | # ADD LINK32 ws2_32.lib advapi32.lib areslib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\areslib\Release" | ||||||
|  |  | ||||||
| !ELSEIF  "$(CFG)" == "adig - Win32 Debug" | !ELSEIF  "$(CFG)" == "adig - Win32 Debug" | ||||||
|  |  | ||||||
| @@ -73,8 +73,8 @@ BSC32=bscmake.exe | |||||||
| # ADD BASE BSC32 /nologo | # ADD BASE BSC32 /nologo | ||||||
| # ADD BSC32 /nologo | # ADD BSC32 /nologo | ||||||
| LINK32=link.exe | LINK32=link.exe | ||||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | # ADD BASE LINK32 ws2_32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||||||
| # ADD LINK32 wsock32.lib areslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\areslib\Debug" | # ADD LINK32 ws2_32.lib advapi32.lib areslib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\areslib\Debug" | ||||||
|  |  | ||||||
| !ENDIF  | !ENDIF  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ RSC=rc.exe | |||||||
| # PROP Use_Debug_Libraries 0 | # PROP Use_Debug_Libraries 0 | ||||||
| # PROP Output_Dir "Release" | # PROP Output_Dir "Release" | ||||||
| # PROP Intermediate_Dir "Release" | # PROP Intermediate_Dir "Release" | ||||||
|  | # PROP Ignore_Export_Lib 0 | ||||||
| # PROP Target_Dir "" | # PROP Target_Dir "" | ||||||
| # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | ||||||
| # ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | # ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | ||||||
| @@ -48,8 +49,8 @@ BSC32=bscmake.exe | |||||||
| # ADD BASE BSC32 /nologo | # ADD BASE BSC32 /nologo | ||||||
| # ADD BSC32 /nologo | # ADD BSC32 /nologo | ||||||
| LINK32=link.exe | LINK32=link.exe | ||||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | # ADD BASE LINK32 ws2_32.lib advapi32.lib /nologo /subsystem:console /machine:I386 | ||||||
| # ADD LINK32 wsock32.lib areslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\areslib\Release" | # ADD LINK32 ws2_32.lib advapi32.lib areslib.lib /nologo /subsystem:console /machine:I386 /libpath:"..\areslib\Release" | ||||||
|  |  | ||||||
| !ELSEIF  "$(CFG)" == "ahost - Win32 Debug" | !ELSEIF  "$(CFG)" == "ahost - Win32 Debug" | ||||||
|  |  | ||||||
| @@ -62,6 +63,7 @@ LINK32=link.exe | |||||||
| # PROP Use_Debug_Libraries 1 | # PROP Use_Debug_Libraries 1 | ||||||
| # PROP Output_Dir "Debug" | # PROP Output_Dir "Debug" | ||||||
| # PROP Intermediate_Dir "Debug" | # PROP Intermediate_Dir "Debug" | ||||||
|  | # PROP Ignore_Export_Lib 0 | ||||||
| # PROP Target_Dir "" | # PROP Target_Dir "" | ||||||
| # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | ||||||
| # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c | ||||||
| @@ -71,8 +73,8 @@ BSC32=bscmake.exe | |||||||
| # ADD BASE BSC32 /nologo | # ADD BASE BSC32 /nologo | ||||||
| # ADD BSC32 /nologo | # ADD BSC32 /nologo | ||||||
| LINK32=link.exe | LINK32=link.exe | ||||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | # ADD BASE LINK32 ws2_32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||||||
| # ADD LINK32 wsock32.lib areslib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\areslib\Debug" | # ADD LINK32 ws2_32.lib advapi32.lib areslib.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\areslib\Debug" | ||||||
|  |  | ||||||
| !ENDIF  | !ENDIF  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
| #                            | (__| |_| |  _ <| |___ | #                            | (__| |_| |  _ <| |___ | ||||||
| #                             \___|\___/|_| \_\_____| | #                             \___|\___/|_| \_\_____| | ||||||
| # | # | ||||||
| # Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | # Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -24,11 +24,11 @@ dnl Process this file with autoconf to produce a configure script. | |||||||
|  |  | ||||||
| AC_PREREQ(2.57) | AC_PREREQ(2.57) | ||||||
|  |  | ||||||
| dnl We don't know the version number "staticly" so we use a dash here | dnl We don't know the version number "statically" so we use a dash here | ||||||
| AC_INIT(curl, [-], [a suitable curl mailing list => http://curl.haxx.se/mail/]) | AC_INIT(curl, [-], [a suitable curl mailing list => http://curl.haxx.se/mail/]) | ||||||
|  |  | ||||||
| dnl configure script copyright | dnl configure script copyright | ||||||
| AC_COPYRIGHT([Copyright (c) 1998 - 2006 Daniel Stenberg, <daniel@haxx.se> | AC_COPYRIGHT([Copyright (c) 1998 - 2008 Daniel Stenberg, <daniel@haxx.se> | ||||||
| This configure script may be copied, distributed and modified under the | This configure script may be copied, distributed and modified under the | ||||||
| terms of the curl license; see COPYING for more details]) | terms of the curl license; see COPYING for more details]) | ||||||
|  |  | ||||||
| @@ -174,6 +174,7 @@ case $host in | |||||||
| esac | esac | ||||||
| AC_MSG_RESULT($mimpure) | AC_MSG_RESULT($mimpure) | ||||||
| AM_CONDITIONAL(MIMPURE, test x$mimpure = xyes) | AM_CONDITIONAL(MIMPURE, test x$mimpure = xyes) | ||||||
|  | AM_CONDITIONAL(STATICLIB, false) | ||||||
|  |  | ||||||
| AC_MSG_CHECKING([if we need BUILDING_LIBCURL]) | AC_MSG_CHECKING([if we need BUILDING_LIBCURL]) | ||||||
| case $host in | case $host in | ||||||
| @@ -185,6 +186,7 @@ case $host in | |||||||
|     then |     then | ||||||
|       AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library]) |       AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library]) | ||||||
|       AC_MSG_RESULT(yes) |       AC_MSG_RESULT(yes) | ||||||
|  |       AM_CONDITIONAL(STATICLIB, true) | ||||||
|     else |     else | ||||||
|       AC_MSG_RESULT(no) |       AC_MSG_RESULT(no) | ||||||
|     fi |     fi | ||||||
| @@ -321,10 +323,29 @@ AC_HELP_STRING([--disable-ldap],[Disable LDAP support]), | |||||||
|        AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) |        AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) | ||||||
|        AC_SUBST(CURL_DISABLE_LDAP, [1]) |        AC_SUBST(CURL_DISABLE_LDAP, [1]) | ||||||
|        ;; |        ;; | ||||||
|   *)   AC_MSG_RESULT(yes) |   *) | ||||||
|  |        case $host in | ||||||
|  |          *-*-cygwin*) | ||||||
|  |            # Force no ldap. config/build process is broken for cygwin | ||||||
|  |            AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) | ||||||
|  |            AC_SUBST(CURL_DISABLE_LDAP, [1]) | ||||||
|  |            AC_MSG_RESULT(no) | ||||||
|            ;; |            ;; | ||||||
|   esac ], |          *) | ||||||
|            AC_MSG_RESULT(yes) |            AC_MSG_RESULT(yes) | ||||||
|  |        esac | ||||||
|  |        ;; | ||||||
|  |   esac ],[ | ||||||
|  |        case $host in | ||||||
|  |          *-*-cygwin*) | ||||||
|  |            # Force no ldap. config/build process is broken for cygwin | ||||||
|  |            AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) | ||||||
|  |            AC_SUBST(CURL_DISABLE_LDAP, [1]) | ||||||
|  |            AC_MSG_RESULT(no) | ||||||
|  |            ;; | ||||||
|  |          *) | ||||||
|  |            AC_MSG_RESULT(yes) | ||||||
|  |        esac ] | ||||||
| ) | ) | ||||||
| AC_MSG_CHECKING([whether to support ldaps]) | AC_MSG_CHECKING([whether to support ldaps]) | ||||||
| AC_ARG_ENABLE(ldaps, | AC_ARG_ENABLE(ldaps, | ||||||
| @@ -901,6 +922,9 @@ dnl ********************************************************************** | |||||||
| dnl Check for GSS-API libraries | dnl Check for GSS-API libraries | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
|  |  | ||||||
|  | dnl check for gss stuff in the /usr as default | ||||||
|  |  | ||||||
|  | GSSAPI_ROOT="/usr" | ||||||
| AC_ARG_WITH(gssapi-includes, | AC_ARG_WITH(gssapi-includes, | ||||||
|   AC_HELP_STRING([--with-gssapi-includes=DIR], |   AC_HELP_STRING([--with-gssapi-includes=DIR], | ||||||
|                  [Specify location of GSSAPI header]), |                  [Specify location of GSSAPI header]), | ||||||
| @@ -921,6 +945,10 @@ AC_ARG_WITH(gssapi, | |||||||
|   GSSAPI_ROOT="$withval" |   GSSAPI_ROOT="$withval" | ||||||
|   if test x"$GSSAPI_ROOT" != xno; then |   if test x"$GSSAPI_ROOT" != xno; then | ||||||
|     want_gss="yes" |     want_gss="yes" | ||||||
|  |     if test x"$GSSAPI_ROOT" = xyes; then | ||||||
|  |       dnl if yes, then use default root | ||||||
|  |       GSSAPI_ROOT="/usr" | ||||||
|  |     fi | ||||||
|   fi |   fi | ||||||
| ]) | ]) | ||||||
|  |  | ||||||
| @@ -932,11 +960,15 @@ if test x"$want_gss" = xyes; then | |||||||
|   if test -z "$GSSAPI_INCS"; then |   if test -z "$GSSAPI_INCS"; then | ||||||
|      if test -f "$GSSAPI_ROOT/bin/krb5-config"; then |      if test -f "$GSSAPI_ROOT/bin/krb5-config"; then | ||||||
|         GSSAPI_INCS=`$GSSAPI_ROOT/bin/krb5-config --cflags gssapi` |         GSSAPI_INCS=`$GSSAPI_ROOT/bin/krb5-config --cflags gssapi` | ||||||
|  |         GSSAPI_LIBS=`$GSSAPI_ROOT/bin/krb5-config --libs gssapi` | ||||||
|      elif test "$GSSAPI_ROOT" != "yes"; then |      elif test "$GSSAPI_ROOT" != "yes"; then | ||||||
|         GSSAPI_INCS="-I$GSSAPI_ROOT/include" |         GSSAPI_INCS="-I$GSSAPI_ROOT/include" | ||||||
|  |         GSSAPI_LIBS="-lgssapi" | ||||||
|      fi |      fi | ||||||
|   fi |   fi | ||||||
|  |  | ||||||
|   CPPFLAGS="$CPPFLAGS $GSSAPI_INCS" |   CPPFLAGS="$CPPFLAGS $GSSAPI_INCS" | ||||||
|  |   LIBS="$LIBS $GSSAPI_LIBS" | ||||||
|  |  | ||||||
|   AC_CHECK_HEADER(gss.h, |   AC_CHECK_HEADER(gss.h, | ||||||
|     [ |     [ | ||||||
| @@ -1292,6 +1324,7 @@ else | |||||||
|   if test "$HAVE_LIBZ" = "1" && test "$HAVE_ZLIB_H" != "1" |   if test "$HAVE_LIBZ" = "1" && test "$HAVE_ZLIB_H" != "1" | ||||||
|   then |   then | ||||||
|     AC_MSG_WARN([configure found only the libz lib, not the header file!]) |     AC_MSG_WARN([configure found only the libz lib, not the header file!]) | ||||||
|  |     HAVE_LIBZ="" | ||||||
|   elif test "$HAVE_LIBZ" != "1" && test "$HAVE_ZLIB_H" = "1" |   elif test "$HAVE_LIBZ" != "1" && test "$HAVE_ZLIB_H" = "1" | ||||||
|   then |   then | ||||||
|     AC_MSG_WARN([configure found only the libz header file, not the lib!]) |     AC_MSG_WARN([configure found only the libz header file, not the lib!]) | ||||||
| @@ -1356,8 +1389,9 @@ if test X"$OPT_LIBSSH2" != Xno; then | |||||||
|   AC_CHECK_HEADERS(libssh2.h, |   AC_CHECK_HEADERS(libssh2.h, | ||||||
|     curl_ssh_msg="enabled (libSSH2)" |     curl_ssh_msg="enabled (libSSH2)" | ||||||
|     LIBSSH2_ENABLED=1 |     LIBSSH2_ENABLED=1 | ||||||
|     AC_DEFINE(USE_LIBSSH2, 1, [if libSSH2 is in use])) |     AC_DEFINE(USE_LIBSSH2, 1, [if libSSH2 is in use]) | ||||||
|     AC_SUBST(USE_LIBSSH2, [1]) |     AC_SUBST(USE_LIBSSH2, [1]) | ||||||
|  |   ) | ||||||
|  |  | ||||||
|   if test X"$OPT_LIBSSH2" != Xoff && |   if test X"$OPT_LIBSSH2" != Xoff && | ||||||
|      test "$LIBSSH2_ENABLED" != "1"; then |      test "$LIBSSH2_ENABLED" != "1"; then | ||||||
| @@ -1516,7 +1550,7 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then | |||||||
|  |  | ||||||
|     dnl Check for functionPK11_CreateGenericObject |     dnl Check for functionPK11_CreateGenericObject | ||||||
|     dnl this is needed for using the PEM PKCS#11 module |     dnl this is needed for using the PEM PKCS#11 module | ||||||
|     AC_CHECK_LIB(nss3, PK11_CreateGenericObject-d, |     AC_CHECK_LIB(nss3, PK11_CreateGenericObject, | ||||||
|      [ |      [ | ||||||
|      AC_DEFINE(HAVE_PK11_CREATEGENERICOBJECT, 1, [if you have the function PK11_CreateGenericObject]) |      AC_DEFINE(HAVE_PK11_CREATEGENERICOBJECT, 1, [if you have the function PK11_CreateGenericObject]) | ||||||
|      AC_SUBST(HAVE_PK11_CREATEGENERICOBJECT, [1]) |      AC_SUBST(HAVE_PK11_CREATEGENERICOBJECT, [1]) | ||||||
| @@ -1566,13 +1600,17 @@ fi dnl OPENSSL != 1 -a GNUTLS_ENABLED != 1 | |||||||
| if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED" = "x"; then | if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED" = "x"; then | ||||||
|   AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.]) |   AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.]) | ||||||
|   AC_MSG_WARN([Use --with-ssl, --with-gnutls or --with-nss to address this.]) |   AC_MSG_WARN([Use --with-ssl, --with-gnutls or --with-nss to address this.]) | ||||||
|  | else | ||||||
|  |   # SSL is enabled, genericly | ||||||
|  |   AC_SUBST(SSL_ENABLED) | ||||||
|  |   SSL_ENABLED="1" | ||||||
| fi | fi | ||||||
|  |  | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| dnl Check for the CA bundle | dnl Check for the CA bundle | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
|  |  | ||||||
| if test X"$USE_NSS$USE_GNUTLS$OPENSSL_ENABLED" != "X"; then | if test X"$SSL_ENABLED" != "X"; then | ||||||
|  |  | ||||||
|   AC_MSG_CHECKING([CA cert bundle install path]) |   AC_MSG_CHECKING([CA cert bundle install path]) | ||||||
|  |  | ||||||
| @@ -1782,7 +1820,7 @@ if test x$cross_compiling != xyes; then | |||||||
|     ) |     ) | ||||||
|   fi |   fi | ||||||
| else | else | ||||||
|   dnl and for crosscompilings |   dnl and for crosscompiling | ||||||
|   AC_CHECK_FUNCS(gmtime_r) |   AC_CHECK_FUNCS(gmtime_r) | ||||||
| fi | fi | ||||||
|  |  | ||||||
| @@ -1827,6 +1865,7 @@ AC_CHECK_HEADERS( | |||||||
|         utime.h \ |         utime.h \ | ||||||
|         sys/utime.h \ |         sys/utime.h \ | ||||||
|         sys/poll.h \ |         sys/poll.h \ | ||||||
|  |         poll.h \ | ||||||
|         sys/resource.h \ |         sys/resource.h \ | ||||||
|         libgen.h \ |         libgen.h \ | ||||||
|         locale.h \ |         locale.h \ | ||||||
| @@ -1874,6 +1913,7 @@ AC_CHECK_SIZEOF(curl_off_t, ,[ | |||||||
| AC_CHECK_SIZEOF(size_t) | AC_CHECK_SIZEOF(size_t) | ||||||
| AC_CHECK_SIZEOF(long) | AC_CHECK_SIZEOF(long) | ||||||
| AC_CHECK_SIZEOF(time_t) | AC_CHECK_SIZEOF(time_t) | ||||||
|  | AC_CHECK_SIZEOF(off_t) | ||||||
|  |  | ||||||
| AC_CHECK_TYPE(long long, | AC_CHECK_TYPE(long long, | ||||||
|    [AC_DEFINE(HAVE_LONGLONG, 1, [if your compiler supports long long])] |    [AC_DEFINE(HAVE_LONGLONG, 1, [if your compiler supports long long])] | ||||||
| @@ -2088,6 +2128,8 @@ if test "$disable_poll" = "no"; then | |||||||
|     AC_RUN_IFELSE([ |     AC_RUN_IFELSE([ | ||||||
| #ifdef HAVE_SYS_POLL_H | #ifdef HAVE_SYS_POLL_H | ||||||
| #include <sys/poll.h> | #include <sys/poll.h> | ||||||
|  | #elif defined(HAVE_POLL_H) | ||||||
|  | #include <poll.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   int main(void) |   int main(void) | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| #                            | (__| |_| |  _ <| |___ | #                            | (__| |_| |  _ <| |___ | ||||||
| #                             \___|\___/|_| \_\_____| | #                             \___|\___/|_| \_\_____| | ||||||
| # | # | ||||||
| # Copyright (C) 2001 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | # Copyright (C) 2001 - 2008, 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 | ||||||
| @@ -83,7 +83,7 @@ while test $# -gt 0; do | |||||||
| 	if test "@USE_SSLEAY@" = "1"; then | 	if test "@USE_SSLEAY@" = "1"; then | ||||||
|           echo "SSL" |           echo "SSL" | ||||||
|           NTLM=1 # OpenSSL implies NTLM |           NTLM=1 # OpenSSL implies NTLM | ||||||
|         elif test -n "@USE_GNUTLS@"; then |         elif test -n "@SSL_ENABLED@"; then | ||||||
|           echo "SSL" |           echo "SSL" | ||||||
|         fi |         fi | ||||||
| 	if test "@KRB4_ENABLED@" = "1"; then | 	if test "@KRB4_ENABLED@" = "1"; then | ||||||
| @@ -113,13 +113,13 @@ while test $# -gt 0; do | |||||||
|     --protocols) |     --protocols) | ||||||
| 	if test "@CURL_DISABLE_HTTP@" != "1"; then | 	if test "@CURL_DISABLE_HTTP@" != "1"; then | ||||||
|           echo "HTTP" |           echo "HTTP" | ||||||
| 	  if test "@USE_SSLEAY@" = "1"; then | 	  if test "@SSL_ENABLED@" = "1"; then | ||||||
|             echo "HTTPS" |             echo "HTTPS" | ||||||
|           fi |           fi | ||||||
|         fi |         fi | ||||||
| 	if test "@CURL_DISABLE_FTP@" != "1"; then | 	if test "@CURL_DISABLE_FTP@" != "1"; then | ||||||
|           echo "FTP" |           echo "FTP" | ||||||
| 	  if test "@USE_SSLEAY@" = "1"; then | 	  if test "@SSL_ENABLED@" = "1"; then | ||||||
|             echo "FTPS" |             echo "FTPS" | ||||||
|           fi |           fi | ||||||
|         fi |         fi | ||||||
| @@ -189,7 +189,7 @@ while test $# -gt 0; do | |||||||
|        	;; |        	;; | ||||||
|  |  | ||||||
|     --libs) |     --libs) | ||||||
| 	if test "X@libdir@" != "X/usr/lib"; then | 	if test "X@libdir@" != "X/usr/lib" -a "X@libdir@" != "X/usr/lib64"; then | ||||||
| 	   CURLLIBDIR="-L@libdir@ " | 	   CURLLIBDIR="-L@libdir@ " | ||||||
| 	else | 	else | ||||||
| 	   CURLLIBDIR="" | 	   CURLLIBDIR="" | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ glib/GTK+ | |||||||
|  |  | ||||||
| Java | Java | ||||||
|  |  | ||||||
|   Maintained by Vic Hanson |   Maintained by [blank] | ||||||
|   http://curl.haxx.se/libcurl/java/ |   http://curl.haxx.se/libcurl/java/ | ||||||
|  |  | ||||||
| Lisp | Lisp | ||||||
| @@ -143,11 +143,20 @@ Rexx | |||||||
|   Written Mark Hessling |   Written Mark Hessling | ||||||
|   http://rexxcurl.sourceforge.net/ |   http://rexxcurl.sourceforge.net/ | ||||||
|  |  | ||||||
|  | RPG | ||||||
|  |  | ||||||
|  |   Support for ILE/RPG on OS/400 is included in source distribution | ||||||
|  |   http://curl.haxx.se/libcurl/ | ||||||
|  |   See packages/OS400/README.OS400 and packages/OS400/curl.inc.in | ||||||
|  |  | ||||||
| Ruby | Ruby | ||||||
|  |  | ||||||
|   Written by Ross Bamford |   curb - written by Ross Bamford | ||||||
|   http://curb.rubyforge.org/ |   http://curb.rubyforge.org/ | ||||||
|  |  | ||||||
|  |   ruby-curl-multi - written by Kristjan Petursson and Keith Rarick | ||||||
|  |   http://curl-multi.rubyforge.org/ | ||||||
|  |  | ||||||
| Scheme | Scheme | ||||||
|  |  | ||||||
|   Bigloo binding by Kirill Lisovsky |   Bigloo binding by Kirill Lisovsky | ||||||
|   | |||||||
| @@ -102,6 +102,8 @@ | |||||||
|  using spaces only (no tabs) and having the opening brace ({) on the same line |  using spaces only (no tabs) and having the opening brace ({) on the same line | ||||||
|  as the if() or while(). |  as the if() or while(). | ||||||
|  |  | ||||||
|  |  Also note that we use if() and while() with no space before the parenthesis. | ||||||
|  |  | ||||||
| 2.3 Commenting | 2.3 Commenting | ||||||
|  |  | ||||||
|  Comment your source code extensively using C comments (/* comment */), DO NOT |  Comment your source code extensively using C comments (/* comment */), DO NOT | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								docs/FAQ
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								docs/FAQ
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| Updated: July 30, 2007 (http://curl.haxx.se/docs/faq.html) | Updated: Dec 10, 2007 (http://curl.haxx.se/docs/faq.html) | ||||||
|                                   _   _ ____  _ |                                   _   _ ____  _ | ||||||
|                               ___| | | |  _ \| | |                               ___| | | |  _ \| | | ||||||
|                              / __| | | | |_) | | |                              / __| | | | |_) | | | ||||||
| @@ -83,6 +83,7 @@ FAQ | |||||||
|   5.10 How do I prevent libcurl from writing the response to stdout? |   5.10 How do I prevent libcurl from writing the response to stdout? | ||||||
|   5.11 How do I make libcurl not receive the whole HTTP response? |   5.11 How do I make libcurl not receive the whole HTTP response? | ||||||
|   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? | ||||||
|  |   5.13 How do I stop an ongoing transfer? | ||||||
|  |  | ||||||
|  6. License Issues |  6. License Issues | ||||||
|   6.1 I have a GPL program, can I use the libcurl library? |   6.1 I have a GPL program, can I use the libcurl library? | ||||||
| @@ -214,8 +215,7 @@ FAQ | |||||||
|   improvements and have them inserted in the main sources (of course on the |   improvements and have them inserted in the main sources (of course on the | ||||||
|   condition that developers agree on that the fixes are good). |   condition that developers agree on that the fixes are good). | ||||||
|  |  | ||||||
|   The full list of the more than 530 contributors is found in the docs/THANKS |   The full list of all contributors is found in the docs/THANKS file. | ||||||
|   file. |  | ||||||
|  |  | ||||||
|   curl is developed by a community, with Daniel at the wheel. |   curl is developed by a community, with Daniel at the wheel. | ||||||
|  |  | ||||||
| @@ -1033,6 +1033,18 @@ FAQ | |||||||
|   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. | ||||||
|  |  | ||||||
|  |   5.13 How do I stop an ongoing transfer? | ||||||
|  |  | ||||||
|  |   There are several ways, but none of them are instant. There is no function | ||||||
|  |   you can call from another thread or similar that will stop it immediately. | ||||||
|  |   Instead you need to make sure that one of the callbacks you use return an | ||||||
|  |   appropriate value that will stop the transfer. | ||||||
|  |  | ||||||
|  |   Suitable callbacks that you can do this with include the progress callback, | ||||||
|  |   the read callback and the write callback. | ||||||
|  |  | ||||||
|  |   If you're using the multi interface, you also stop a transfer by removing | ||||||
|  |   the particular easy handle from the multi stack. | ||||||
|  |  | ||||||
| 6. License Issues | 6. License Issues | ||||||
|  |  | ||||||
|   | |||||||
| @@ -188,7 +188,7 @@ Win32 | |||||||
|    environment variables, for example: |    environment variables, for example: | ||||||
|  |  | ||||||
|      set ZLIB_PATH=c:\zlib-1.2.3 |      set ZLIB_PATH=c:\zlib-1.2.3 | ||||||
|      set OPENSSL_PATH=c:\openssl-0.9.8e |      set OPENSSL_PATH=c:\openssl-0.9.8g | ||||||
|      set LIBSSH2_PATH=c:\libssh2-0.17 |      set LIBSSH2_PATH=c:\libssh2-0.17 | ||||||
|  |  | ||||||
|    ATTENTION: if you want to build with libssh2 support you have to use latest |    ATTENTION: if you want to build with libssh2 support you have to use latest | ||||||
| @@ -257,7 +257,7 @@ Win32 | |||||||
|    Before running nmake define the OPENSSL_PATH environment variable with |    Before running nmake define the OPENSSL_PATH environment variable with | ||||||
|    the root/base directory of OpenSSL, for example: |    the root/base directory of OpenSSL, for example: | ||||||
|  |  | ||||||
|      set OPENSSL_PATH=c:\openssl-0.9.8e |      set OPENSSL_PATH=c:\openssl-0.9.8g | ||||||
|  |  | ||||||
|    Then run 'nmake vc-ssl' or 'nmake vc-ssl-dll' in curl's root |    Then run 'nmake vc-ssl' or 'nmake vc-ssl-dll' in curl's root | ||||||
|    directory.  'nmake vc-ssl' will create a libcurl static and dynamic |    directory.  'nmake vc-ssl' will create a libcurl static and dynamic | ||||||
| @@ -521,7 +521,7 @@ NetWare | |||||||
|      http://www.gknw.net/development/ossl/netware/ |      http://www.gknw.net/development/ossl/netware/ | ||||||
|      for CLIB-based builds OpenSSL needs to be patched to build with BSD |      for CLIB-based builds OpenSSL needs to be patched to build with BSD | ||||||
|      sockets (currently only a winsock-based CLIB build is supported): |      sockets (currently only a winsock-based CLIB build is supported): | ||||||
|      http://www.gknw.net/development/ossl/netware/patches/v_0.9.8e/openssl-0.9.8e.diff |      http://www.gknw.net/development/ossl/netware/patches/v_0.9.8g/openssl-0.9.8g.diff | ||||||
|    - optional SSH2 sources (version 0.17 or later); |    - optional SSH2 sources (version 0.17 or later); | ||||||
|  |  | ||||||
|    Set a search path to your compiler, linker and tools; on Linux make |    Set a search path to your compiler, linker and tools; on Linux make | ||||||
| @@ -808,10 +808,12 @@ PORTS | |||||||
|         - ia64 Linux 2.3.99 |         - ia64 Linux 2.3.99 | ||||||
|         - m68k AmigaOS 3 |         - m68k AmigaOS 3 | ||||||
|         - m68k Linux |         - m68k Linux | ||||||
|  |         - m68k uClinux | ||||||
|         - m68k OpenBSD |         - m68k OpenBSD | ||||||
|         - m88k dg-dgux5.4R3.00 |         - m88k dg-dgux5.4R3.00 | ||||||
|         - s390 Linux |         - s390 Linux | ||||||
|         - XScale/PXA250 Linux 2.4 |         - XScale/PXA250 Linux 2.4 | ||||||
|  |         - Nios II uClinux | ||||||
|  |  | ||||||
| Useful URLs | Useful URLs | ||||||
| =========== | =========== | ||||||
|   | |||||||
| @@ -97,7 +97,9 @@ Library | |||||||
|  |  | ||||||
|    ... analyzes the URL, it separates the different components and connects to |    ... analyzes the URL, it separates the different components and connects to | ||||||
|    the remote host. This may involve using a proxy and/or using SSL. The |    the remote host. This may involve using a proxy and/or using SSL. The | ||||||
|    Curl_gethost() function in lib/hostip.c is used for looking up host names. |    Curl_resolv() function in lib/hostip.c is used for looking up host names | ||||||
|  |    (it does then use the proper underlying method, which may vary between | ||||||
|  |    platforms and builds). | ||||||
|  |  | ||||||
|    When Curl_connect is done, we are connected to the remote site. Then it is |    When Curl_connect is done, we are connected to the remote site. Then it is | ||||||
|    time to tell the server to get a document/file. Curl_do() arranges this. |    time to tell the server to get a document/file. Curl_do() arranges this. | ||||||
| @@ -122,17 +124,20 @@ Library | |||||||
|    Curl_Transfer() function (in lib/transfer.c) to setup the transfer and |    Curl_Transfer() function (in lib/transfer.c) to setup the transfer and | ||||||
|    returns. |    returns. | ||||||
|  |  | ||||||
|    Starting in 7.9.1, if this DO function fails and the connection is being |    If this DO function fails and the connection is being re-used, libcurl will | ||||||
|    re-used, libcurl will then close this connection, setup a new connection |    then close this connection, setup a new connection and re-issue the DO | ||||||
|    and re-issue the DO request on that. This is because there is no way to be |    request on that. This is because there is no way to be perfectly sure that | ||||||
|    perfectly sure that we have discovered a dead connection before the DO |    we have discovered a dead connection before the DO function and thus we | ||||||
|    function and thus we might wrongly be re-using a connection that was closed |    might wrongly be re-using a connection that was closed by the remote peer. | ||||||
|    by the remote peer. |  | ||||||
|  |    Some time during the DO function, the Curl_setup_transfer() function must | ||||||
|  |    be called with some basic info about the upcoming transfer: what socket(s) | ||||||
|  |    to read/write and the expected file tranfer sizes (if known). | ||||||
|  |  | ||||||
|  o Transfer() |  o Transfer() | ||||||
|  |  | ||||||
|    Curl_perform() then calls Transfer() in lib/transfer.c that performs |    Curl_perform() then calls Transfer() in lib/transfer.c that performs the | ||||||
|    the entire file transfer. |    entire file transfer. | ||||||
|  |  | ||||||
|    During transfer, the progress functions in lib/progress.c are called at a |    During transfer, the progress functions in lib/progress.c are called at a | ||||||
|    frequent interval (or at the user's choice, a specified callback might get |    frequent interval (or at the user's choice, a specified callback might get | ||||||
| @@ -236,9 +241,8 @@ Library | |||||||
|  URL encoding and decoding, called escaping and unescaping in the source code, |  URL encoding and decoding, called escaping and unescaping in the source code, | ||||||
|  is found in lib/escape.c. |  is found in lib/escape.c. | ||||||
|  |  | ||||||
|  While transfering data in Transfer() a few functions might get |  While transfering data in Transfer() a few functions might get used. | ||||||
|  used. curl_getdate() in lib/getdate.c is for HTTP date comparisons (and |  curl_getdate() in lib/parsedate.c is for HTTP date comparisons (and more). | ||||||
|  more). |  | ||||||
|  |  | ||||||
|  lib/getenv.c offers curl_getenv() which is for reading environment variables |  lib/getenv.c offers curl_getenv() which is for reading environment variables | ||||||
|  in a neat platform independent way. That's used in the client, but also in |  in a neat platform independent way. That's used in the client, but also in | ||||||
| @@ -254,10 +258,6 @@ Library | |||||||
|  A function named curl_version() that returns the full curl version string is |  A function named curl_version() that returns the full curl version string is | ||||||
|  found in lib/version.c. |  found in lib/version.c. | ||||||
|  |  | ||||||
|  If authentication is requested but no password is given, a getpass_r() clone |  | ||||||
|  exists in lib/getpass.c. libcurl offers a custom callback that can be used |  | ||||||
|  instead of this, but it doesn't change much to us. |  | ||||||
|  |  | ||||||
| Persistent Connections | Persistent Connections | ||||||
| ====================== | ====================== | ||||||
|  |  | ||||||
| @@ -269,9 +269,11 @@ Persistent Connections | |||||||
|    all the options etc that the library-user may choose. |    all the options etc that the library-user may choose. | ||||||
|  o The 'SessionHandle' struct holds the "connection cache" (an array of |  o The 'SessionHandle' struct holds the "connection cache" (an array of | ||||||
|    pointers to 'connectdata' structs). There's one connectdata struct |    pointers to 'connectdata' structs). There's one connectdata struct | ||||||
|    allocated for each connection that libcurl knows about. |    allocated for each connection that libcurl knows about. Note that when you | ||||||
|  o This also enables the 'curl handle' to be reused on subsequent transfers, |    use the multi interface, the multi handle will hold the connection cache | ||||||
|    something that was illegal before libcurl 7.7. |    and not the particular easy handle. This of course to allow all easy handles | ||||||
|  |    in a multi stack to be able to share and re-use connections. | ||||||
|  |  o This enables the 'curl handle' to be reused on subsequent transfers. | ||||||
|  o When we are about to perform a transfer with curl_easy_perform(), we first |  o When we are about to perform a transfer with curl_easy_perform(), we first | ||||||
|    check for an already existing connection in the cache that we can use, |    check for an already existing connection in the cache that we can use, | ||||||
|    otherwise we create a new one and add to the cache. If the cache is full |    otherwise we create a new one and add to the cache. If the cache is full | ||||||
| @@ -281,11 +283,46 @@ Persistent Connections | |||||||
|  o When the transfer operation is complete, we try to leave the connection |  o When the transfer operation is complete, we try to leave the connection | ||||||
|    open. Particular options may tell us not to, and protocols may signal |    open. Particular options may tell us not to, and protocols may signal | ||||||
|    closure on connections and then we don't keep it open of course. |    closure on connections and then we don't keep it open of course. | ||||||
|  o When curl_easy_cleanup() is called, we close all still opened connections. |  o When curl_easy_cleanup() is called, we close all still opened connections, | ||||||
|  |    unless of course the multi interface "owns" the connections. | ||||||
|  |  | ||||||
|  You do realize that the curl handle must be re-used in order for the |  You do realize that the curl handle must be re-used in order for the | ||||||
|  persistent connections to work. |  persistent connections to work. | ||||||
|  |  | ||||||
|  | multi interface/non-blocking | ||||||
|  | ============================ | ||||||
|  |  | ||||||
|  |  We make an effort to provide a non-blocking interface to the library, the | ||||||
|  |  multi interface. To make that interface work as good as possible, no | ||||||
|  |  low-level functions within libcurl must be written to work in a blocking | ||||||
|  |  manner. | ||||||
|  |  | ||||||
|  |  One of the primary reasons we introduced c-ares support was to allow the name | ||||||
|  |  resolve phase to be perfectly non-blocking as well. | ||||||
|  |  | ||||||
|  |  The ultimate goal is to provide the easy interface simply by wrapping the | ||||||
|  |  multi interface functions and thus treat everything internally as the multi | ||||||
|  |  interface is the single interface we have. | ||||||
|  |  | ||||||
|  |  The FTP and the SFTP/SCP protocols are thus perfect examples of how we adapt | ||||||
|  |  and adjust the code to allow non-blocking operations even on multi-stage | ||||||
|  |  protocols. The DICT, TELNET and TFTP are crappy examples and they are subject | ||||||
|  |  for rewrite in the future to better fit the libcurl protocol family. | ||||||
|  |  | ||||||
|  | SSL libraries | ||||||
|  | ============= | ||||||
|  |  | ||||||
|  |  Originally libcurl supported SSLeay for SSL/TLS transports, but that was then | ||||||
|  |  extended to its successor OpenSSL but has since also been extended to several | ||||||
|  |  other SSL/TLS libraries and we expect and hope to further extend the support | ||||||
|  |  in future libcurl versions. | ||||||
|  |  | ||||||
|  |  To deal with this internally in the best way possible, we have a generic SSL | ||||||
|  |  function API as provided by the sslgen.[ch] system, and they are the only SSL | ||||||
|  |  functions we must use from within libcurl. sslgen is then crafted to use the | ||||||
|  |  appropriate lower-level function calls to whatever SSL library that is in | ||||||
|  |  use. | ||||||
|  |  | ||||||
| Library Symbols | Library Symbols | ||||||
| =============== | =============== | ||||||
|   |   | ||||||
| @@ -309,6 +346,13 @@ Return Codes and Informationals | |||||||
|  them. They are best used when revealing information that isn't otherwise |  them. They are best used when revealing information that isn't otherwise | ||||||
|  obvious. |  obvious. | ||||||
|  |  | ||||||
|  | API/ABI | ||||||
|  | ======= | ||||||
|  |  | ||||||
|  |  We make an effort to not export or show internals or how internals work, as | ||||||
|  |  that makes it easier to keep a solid API/ABI over time. See docs/libcurl/ABI | ||||||
|  |  for our promise to users. | ||||||
|  |  | ||||||
| Client | Client | ||||||
| ====== | ====== | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,24 @@ 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! | ||||||
|  |  | ||||||
|  | 52. Gautam Kachroo's issue that identifies a problem with the multi interface | ||||||
|  |   where a connection can be re-used without actually being properly | ||||||
|  |   SSL-negoatiated: | ||||||
|  |   http://curl.haxx.se/mail/lib-2008-01/0277.html | ||||||
|  |  | ||||||
|  | 51.Kevin Reed's reported problem with a proxy when doing CONNECT and it | ||||||
|  |   wants NTLM and close the connection to the initial CONNECT response: | ||||||
|  |   http://curl.haxx.se/bug/view.cgi?id=1879375 | ||||||
|  |  | ||||||
|  | 50. Curl_done() and pipelning aren't totally cool together: | ||||||
|  |   http://curl.haxx.se/mail/lib-2008-01/0330.html | ||||||
|  |  | ||||||
|  | 49. If using --retry and the transfer timeouts (possibly due to using -m or | ||||||
|  |   -y/-Y) the next attempt doesn't resume the transfer properly from what was | ||||||
|  |   downloaded in the previous attempt but will truncate and restart at the | ||||||
|  |   original position where it was at before the previous failed attempt. See | ||||||
|  |   http://curl.haxx.se/mail/lib-2008-01/0080.html | ||||||
|  |  | ||||||
| 48. If a CONNECT response-headers are larger than BUFSIZE (16KB) when the | 48. If a CONNECT response-headers are larger than BUFSIZE (16KB) when the | ||||||
|   connection is meant to be kept alive (like for NTLM proxy auth), the |   connection is meant to be kept alive (like for NTLM proxy auth), the | ||||||
|   function will return prematurely and will confuse the rest of the HTTP |   function will return prematurely and will confuse the rest of the HTTP | ||||||
| @@ -43,23 +61,9 @@ may have been fixed since this was written! | |||||||
|   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=1556528, | ||||||
|  |  | ||||||
| 33. Doing multi-pass HTTP authentication on a non-default port does not work. |  | ||||||
|   This happens because the multi-pass code abuses the redirect following code |  | ||||||
|   for doing multiple requests, and when we following redirects to an absolute |  | ||||||
|   URL we must use the newly specified port and not the one specified in the |  | ||||||
|   original URL. A proper fix to this would need to separate the negotiation |  | ||||||
|   "redirect" from an actual redirect. |  | ||||||
|  |  | ||||||
| 32. (At least on Windows) If libcurl is built with c-ares and there's no DNS |  | ||||||
|   server configured in the system, the ares_init() call fails and thus |  | ||||||
|   curl_easy_init() fails as well. This causes weird effects for people who use |  | ||||||
|   numerical IP addresses only. |  | ||||||
|  |  | ||||||
| 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. Similarly, it might |   run that might be needed only for building libcurl. Further, curl-config | ||||||
|   include options that perhaps aren't suitable both for static and dynamic |   --cflags suffers from the same effects with CFLAGS/CPPFLAGS. | ||||||
|   linking. Further, curl-config --cflags suffers from the same effects with |  | ||||||
|   CFLAGS/CPPFLAGS. |  | ||||||
|  |  | ||||||
| 30. You need to use -g to the command line tool in order to use RFC2732-style | 30. You need to use -g to the command line tool in order to use RFC2732-style | ||||||
|   IPv6 numerical addresses in URLs. |   IPv6 numerical addresses in URLs. | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ Albert Chin-A-Young | |||||||
| Albert Choy | Albert Choy | ||||||
| Ale Vesely | Ale Vesely | ||||||
| Aleksandar Milivojevic | Aleksandar Milivojevic | ||||||
|  | Alex Fishman | ||||||
| Alex Neblett | Alex Neblett | ||||||
| Alex Suykov | Alex Suykov | ||||||
| Alex aka WindEagle | Alex aka WindEagle | ||||||
| @@ -19,6 +20,7 @@ Alexander Kourakos | |||||||
| Alexander Krasnostavsky | Alexander Krasnostavsky | ||||||
| Alexander Lazic | Alexander Lazic | ||||||
| Alexander Zhuravlev | Alexander Zhuravlev | ||||||
|  | Alexey Pesternikov | ||||||
| Alexey Simak | Alexey Simak | ||||||
| Alexis Carvalho | Alexis Carvalho | ||||||
| Allen Pulsifer | Allen Pulsifer | ||||||
| @@ -229,6 +231,7 @@ Ignacio Vazquez-Abrams | |||||||
| Igor Polyakov | Igor Polyakov | ||||||
| Ilguiz Latypov | Ilguiz Latypov | ||||||
| Ilja van Sprundel | Ilja van Sprundel | ||||||
|  | Immanuel Gregoire | ||||||
| Ingmar Runge | Ingmar Runge | ||||||
| Ingo Ralf Blum | Ingo Ralf Blum | ||||||
| Ingo Wilken | Ingo Wilken | ||||||
| @@ -274,6 +277,7 @@ John Janssen | |||||||
| John Kelly | John Kelly | ||||||
| John Lask | John Lask | ||||||
| John McGowan | John McGowan | ||||||
|  | Johnny Luong | ||||||
| Jon Grubbs | Jon Grubbs | ||||||
| Jon Travis | Jon Travis | ||||||
| Jon Turner | Jon Turner | ||||||
| @@ -308,6 +312,7 @@ Kent Boortz | |||||||
| Kevin Fisk | Kevin Fisk | ||||||
| Kevin Lussier | Kevin Lussier | ||||||
| Kevin Roth | Kevin Roth | ||||||
|  | Kim Rinnewitz | ||||||
| Kimmo Kinnunen | Kimmo Kinnunen | ||||||
| Kjell Ericson | Kjell Ericson | ||||||
| Kjetil Jacobsen | Kjetil Jacobsen | ||||||
| @@ -348,6 +353,7 @@ Marco G. Salvagno | |||||||
| Marcus Webster | Marcus Webster | ||||||
| Mario Schroeder | Mario Schroeder | ||||||
| Mark Butler | Mark Butler | ||||||
|  | Mark Davies | ||||||
| Mark Eichin | Mark Eichin | ||||||
| Mark Lentczner | Mark Lentczner | ||||||
| Markus Koetter | Markus Koetter | ||||||
| @@ -368,6 +374,7 @@ Matt Witherspoon | |||||||
| Matthew Blain | Matthew Blain | ||||||
| Matthew Clarke | Matthew Clarke | ||||||
| Maurice Barnum | Maurice Barnum | ||||||
|  | Max Katsev | ||||||
| Mekonikum | Mekonikum | ||||||
| Mettgut Jamalla | Mettgut Jamalla | ||||||
| Michael Benedict | Michael Benedict | ||||||
| @@ -440,6 +447,7 @@ Peter Wullinger | |||||||
| Peteris Krumins | Peteris Krumins | ||||||
| Phil Karn | Phil Karn | ||||||
| Philip Gladstone | Philip Gladstone | ||||||
|  | Philip Langdale | ||||||
| Philippe Hameau | Philippe Hameau | ||||||
| Philippe Raoult | Philippe Raoult | ||||||
| Philippe Vaucher | Philippe Vaucher | ||||||
| @@ -575,6 +583,7 @@ Vilmos Nebehaj | |||||||
| Vincent Bronner | Vincent Bronner | ||||||
| Vincent Penquerc'h | Vincent Penquerc'h | ||||||
| Vincent Sanders | Vincent Sanders | ||||||
|  | Vladimir Lazarenko | ||||||
| Vojtech Janota | Vojtech Janota | ||||||
| Vojtech Minarik | Vojtech Minarik | ||||||
| Walter J. Mack | Walter J. Mack | ||||||
|   | |||||||
							
								
								
									
										529
									
								
								docs/TODO
									
									
									
									
									
								
							
							
						
						
									
										529
									
								
								docs/TODO
									
									
									
									
									
								
							| @@ -4,257 +4,445 @@ | |||||||
|                             | (__| |_| |  _ <| |___  |                             | (__| |_| |  _ <| |___  | ||||||
|                              \___|\___/|_| \_\_____| |                              \___|\___/|_| \_\_____| | ||||||
|  |  | ||||||
| TODO |                 Things that could be nice to do in the future | ||||||
|  |  | ||||||
|  Things to do in project cURL. Please tell us what you think, contribute and |  Things to do in project cURL. Please tell us what you think, contribute and | ||||||
|  send us patches that improve things! Also check the http://curl.haxx.se/dev |  send us patches that improve things! | ||||||
|  web section for various technical development notes. |  | ||||||
|  |  | ||||||
|  All bugs documented in the KNOWN_BUGS document are subject for fixing! |  All bugs documented in the KNOWN_BUGS document are subject for fixing! | ||||||
|  |  | ||||||
|  LIBCURL |  1. libcurl | ||||||
|  |  1.1 Zero-copy interface | ||||||
|  |  1.2 More data sharing | ||||||
|  |  1.3 struct lifreq | ||||||
|  |  1.4 Get IP address | ||||||
|  |  1.5 c-ares ipv6 | ||||||
|  |  1.6 configure-based info in public headers | ||||||
|  |  | ||||||
|  * Introduce another callback interface for upload/download that makes one |  2. libcurl - multi interface | ||||||
|    less copy of data and thus a faster operation. |  2.1 More non-blocking | ||||||
|  |  2.2 Pause transfers | ||||||
|  |  2.3 Remove easy interface internally | ||||||
|  |  2.4 Avoid having to remove/readd handles | ||||||
|  |  | ||||||
|  |  3. Documentation | ||||||
|  |  3.1  More and better | ||||||
|  |  | ||||||
|  |  4. FTP | ||||||
|  |  4.1 PRET | ||||||
|  |  4.2 Alter passive/active on failure and retry | ||||||
|  |  4.3 Earlier bad letter detection | ||||||
|  |  4.4 REST for large files | ||||||
|  |  4.5 FTP proxy support | ||||||
|  |  4.6 PORT port range | ||||||
|  |  4.7 ASCII support | ||||||
|  |  | ||||||
|  |  5. HTTP | ||||||
|  |  5.1 Other HTTP versions with CONNECT | ||||||
|  |  5.2 Better persistancy for HTTP 1.0 | ||||||
|  |  5.3 support FF3 sqlite cookie files | ||||||
|  |  | ||||||
|  |  6. TELNET | ||||||
|  |  6.1 ditch stdin | ||||||
|  |  6.2 ditch telnet-specific select | ||||||
|  |  | ||||||
|  |  7. SSL | ||||||
|  |  7.1 Disable specific versions | ||||||
|  |  7.2 Provide mytex locking API | ||||||
|  |  7.3 dumpcert | ||||||
|  |  7.4 Evaluate SSL patches | ||||||
|  |  7.5 Cache OpenSSL contexts | ||||||
|  |  7.6 Export session ids | ||||||
|  |  7.7 Provide callback for cert verfication | ||||||
|  |  7.8 Support other SSL libraries | ||||||
|  |  7.9  Support SRP on the TLS layer | ||||||
|  |  7.10 improve configure --with-ssl | ||||||
|  |  | ||||||
|  |  8. GnuTLS | ||||||
|  |  8.1 Make NTLM work without OpenSSL functions | ||||||
|  |  8.2 SSl engine stuff | ||||||
|  |  8.3 SRP | ||||||
|  |  8.4 non-blocking | ||||||
|  |  8.5 check connection | ||||||
|  |  | ||||||
|  |  9. LDAP | ||||||
|  |  9.1 ditch ldap-specific select | ||||||
|  |  | ||||||
|  |  10. New protocols | ||||||
|  |  10.1 RTSP | ||||||
|  |  10.2 RSYNC | ||||||
|  |  10.3 RTMP | ||||||
|  |  | ||||||
|  |  11. Client | ||||||
|  |  11.1 Content-Disposition | ||||||
|  |  11.2 sync | ||||||
|  |  11.3 glob posts | ||||||
|  |  11.4 prevent file overwriting | ||||||
|  |  11.5 ftp wildcard download | ||||||
|  |  11.6 simultaneous parallel transfers | ||||||
|  |  11.7 provide formpost headers | ||||||
|  |  11.8 url-specific options | ||||||
|  |  | ||||||
|  |  12. Build | ||||||
|  |  12.1 roffit | ||||||
|  |  | ||||||
|  |  13. Test suite | ||||||
|  |  13.1 SSL tunnel | ||||||
|  |  13.2 nicer lacking perl message | ||||||
|  |  13.3 more protocols supported | ||||||
|  |  13.4 more platforms supported | ||||||
|  |  | ||||||
|  |  14. Next SONAME bump | ||||||
|  |  14.1 http-style HEAD output for ftp | ||||||
|  |  14.2 combine error codes | ||||||
|  |  14.3 extend CURLOPT_SOCKOPTFUNCTION prototype | ||||||
|  |  | ||||||
|  |  15. Next major release | ||||||
|  |  15.1 cleanup return codes | ||||||
|  |  15.2 remove obsolete defines | ||||||
|  |  15.3 size_t | ||||||
|  |  15.4 remove several functions | ||||||
|  |  15.5 remove CURLOPT_FAILONERROR | ||||||
|  |  15.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE | ||||||
|  |  | ||||||
|  | ============================================================================== | ||||||
|  |  | ||||||
|  | 1. libcurl | ||||||
|  |  | ||||||
|  | 1.1 Zero-copy interface | ||||||
|  |  | ||||||
|  |  Introdue another callback interface for upload/download that makes one less | ||||||
|  |  copy of data and thus a faster operation. | ||||||
|  [http://curl.haxx.se/dev/no_copy_callbacks.txt] |  [http://curl.haxx.se/dev/no_copy_callbacks.txt] | ||||||
|  |  | ||||||
|  * More data sharing. curl_share_* functions already exist and work, and they | 1.2 More data sharing | ||||||
|    can be extended to share more. For example, enable sharing of the ares |  | ||||||
|    channel and the connection cache. |  | ||||||
|  |  | ||||||
|  * Introduce a new error code indicating authentication problems (for proxy |  curl_share_* functions already exist and work, and they can be extended to | ||||||
|    CONNECT error 407 for example). This cannot be an error code, we must not |  share more. For example, enable sharing of the ares channel and the | ||||||
|    return informational stuff as errors, consider a new info returned by |  connection cache. | ||||||
|    curl_easy_getinfo() http://curl.haxx.se/bug/view.cgi?id=845941 |  | ||||||
|  |  | ||||||
|  * Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and | 1.3 struct lifreq | ||||||
|  |  | ||||||
|  |  Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and | ||||||
|  SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete. |  SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete. | ||||||
|    To support ipv6 interface addresses properly. |  To support ipv6 interface addresses for network interfaces properly. | ||||||
|  |  | ||||||
|  * Add the following to curl_easy_getinfo(): GET_HTTP_IP, GET_FTP_IP and | 1.4 Get IP address | ||||||
|    GET_FTP_DATA_IP. Return a string with the used IP. Suggested by Alan. |  | ||||||
|  |  | ||||||
|  * Add option that changes the interval in which the progress callback is |  Add the following to curl_easy_getinfo(): GET_HTTP_IP, GET_FTP_IP and | ||||||
|    called at most. |  GET_FTP_DATA_IP. Return a string with the used IP. | ||||||
|  |  | ||||||
|  * Make libcurl built with c-ares use c-ares' IPv6 abilities. They weren't | 1.5 c-ares ipv6 | ||||||
|  |  | ||||||
|  |  Make libcurl built with c-ares use c-ares' IPv6 abilities. They weren't | ||||||
|  present when we first added c-ares support but they have been added since! |  present when we first added c-ares support but they have been added since! | ||||||
|  When this is done and works, we can actually start considering making c-ares |  When this is done and works, we can actually start considering making c-ares | ||||||
|  powered libcurl the default build (which of course would require that we'd |  powered libcurl the default build (which of course would require that we'd | ||||||
|  bundle the c-ares source code in the libcurl source code releases). |  bundle the c-ares source code in the libcurl source code releases). | ||||||
|  |  | ||||||
|  * Make the curl/*.h headers include the proper system includes based on what | 1.6 configure-based info in public headers | ||||||
|    was present at the time when configure was run. Currently, the sys/select.h |  | ||||||
|    header is for example included by curl/multi.h only on specific platforms |  | ||||||
|    we know MUST have it. This is error-prone. We therefore want the header |  | ||||||
|    files to adapt to configure results. Those results must be stored in a new |  | ||||||
|    header and they must use a curl name space, i.e not be HAVE_* prefix (as |  | ||||||
|    that would risk collide with other apps that use libcurl and that runs |  | ||||||
|    configure). |  | ||||||
|  |  | ||||||
|    Work on this has been started but hasn't been finished, and the initial |  Make the public headers include the proper system includes based on what was | ||||||
|    patch and some details are found here: |  present at the time when configure was run. Currently, the sys/select.h | ||||||
|  |  header is for example included by curl/multi.h only on specific platforms we | ||||||
|  |  know MUST have it. This is error-prone. We therefore want the header files to | ||||||
|  |  adapt to configure results. Those results must be stored in a new header and | ||||||
|  |  they must use a curl name space, i.e not be HAVE_* prefix (as that would risk | ||||||
|  |  collide with other apps that use libcurl and that runs configure). | ||||||
|  |  | ||||||
|  |  Work on this has been started but hasn't been finished, and the initial patch | ||||||
|  |  and some details are found here: | ||||||
|  http://curl.haxx.se/mail/lib-2006-12/0084.html |  http://curl.haxx.se/mail/lib-2006-12/0084.html | ||||||
|  |  | ||||||
|  LIBCURL - multi interface |  The remaining problems to solve involve the platforms that can't run | ||||||
|  |  configure. | ||||||
|  |  | ||||||
|  * Make sure we don't ever loop because of non-blocking sockets return | 2. libcurl - multi interface | ||||||
|  |  | ||||||
|  | 2.1 More non-blocking | ||||||
|  |  | ||||||
|  |  Make sure we don't ever loop because of non-blocking sockets return | ||||||
|  EWOULDBLOCK or similar. The GnuTLS connection etc. |  EWOULDBLOCK or similar. The GnuTLS connection etc. | ||||||
|  |  | ||||||
|  * Make transfers treated more carefully. We need a way to tell libcurl we | 2.2 Pause transfers | ||||||
|    have data to write, as the current system expects us to upload data each |  | ||||||
|    time the socket is writable and there is no way to say that we want to |  | ||||||
|    upload data soon just not right now, without that aborting the upload. The |  | ||||||
|    opposite situation should be possible as well, that we tell libcurl we're |  | ||||||
|    ready to accept read data. Today libcurl feeds the data as soon as it is |  | ||||||
|    available for reading, no matter what. |  | ||||||
|  |  | ||||||
|  * Make curl_easy_perform() a wrapper-function that simply creates a multi |  Make transfers treated more carefully. We need a way to tell libcurl we have | ||||||
|  |  data to write, as the current system expects us to upload data each time the | ||||||
|  |  socket is writable and there is no way to say that we want to upload data | ||||||
|  |  soon just not right now, without that aborting the upload. The opposite | ||||||
|  |  situation should be possible as well, that we tell libcurl we're ready to | ||||||
|  |  accept read data. Today libcurl feeds the data as soon as it is available for | ||||||
|  |  reading, no matter what. | ||||||
|  |  | ||||||
|  | 2.3 Remove easy interface internally | ||||||
|  |  | ||||||
|  |  Make curl_easy_perform() a wrapper-function that simply creates a multi | ||||||
|  handle, adds the easy handle to it, runs curl_multi_perform() until the |  handle, adds the easy handle to it, runs curl_multi_perform() until the | ||||||
|  transfer is done, then detach the easy handle, destroy the multi handle and |  transfer is done, then detach the easy handle, destroy the multi handle and | ||||||
|  return the easy handle's return code. This will thus make everything |  return the easy handle's return code. This will thus make everything | ||||||
|  internally use and assume the multi interface. The select()-loop should use |  internally use and assume the multi interface. The select()-loop should use | ||||||
|  curl_multi_socket(). |  curl_multi_socket(). | ||||||
|  |  | ||||||
|  * curl_multi_handle_control() - this can control the easy handle (while) | 2.4 Avoid having to remove/readd handles | ||||||
|    added to a multi handle in various ways: |  | ||||||
|  |  curl_multi_handle_control() - this can control the easy handle (while) added | ||||||
|  |  to a multi handle in various ways: | ||||||
|  |  | ||||||
|  o RESTART, unconditionally restart this easy handle's transfer from the |  o RESTART, unconditionally restart this easy handle's transfer from the | ||||||
|    start, re-init the state |    start, re-init the state | ||||||
|  |  | ||||||
|  o RESTART_COMPLETED, restart this easy handle's transfer but only if the |  o RESTART_COMPLETED, restart this easy handle's transfer but only if the | ||||||
|    existing transfer has already completed and it is in a "finished state". |    existing transfer has already completed and it is in a "finished state". | ||||||
|  |  | ||||||
|  o STOP, just stop this transfer and consider it completed |  o STOP, just stop this transfer and consider it completed | ||||||
|  |  | ||||||
|  o PAUSE? |  o PAUSE? | ||||||
|  |  | ||||||
|  o RESUME? |  o RESUME? | ||||||
|  |  | ||||||
|  DOCUMENTATION | 3. Documentation | ||||||
|  |  | ||||||
|  * More and better | 3.1  More and better | ||||||
|  |  | ||||||
|  FTP |  Exactly | ||||||
|  |  | ||||||
|  * PRET is a command that primarily "drftpd" supports, which could be useful | 4. FTP | ||||||
|  |  | ||||||
|  | 4.1 PRET | ||||||
|  |  | ||||||
|  |  PRET is a command that primarily "drftpd" supports, which could be useful | ||||||
|  when using libcurl against such a server. It is a non-standard and a rather |  when using libcurl against such a server. It is a non-standard and a rather | ||||||
|  oddly designed command, but... |  oddly designed command, but... | ||||||
|  http://curl.haxx.se/bug/feature.cgi?id=1729967 |  http://curl.haxx.se/bug/feature.cgi?id=1729967 | ||||||
|  |  | ||||||
|  * When trying to connect passively to a server which only supports active | 4.2 Alter passive/active on failure and retry | ||||||
|  |  | ||||||
|  |  When trying to connect passively to a server which only supports active | ||||||
|  connections, libcurl returns CURLE_FTP_WEIRD_PASV_REPLY and closes the |  connections, libcurl returns CURLE_FTP_WEIRD_PASV_REPLY and closes the | ||||||
|  connection. There could be a way to fallback to an active connection (and |  connection. There could be a way to fallback to an active connection (and | ||||||
|  vice versa). http://curl.haxx.se/bug/feature.cgi?id=1754793 |  vice versa). http://curl.haxx.se/bug/feature.cgi?id=1754793 | ||||||
|  |  | ||||||
|  * Make the detection of (bad) %0d and %0a codes in FTP url parts earlier in | 4.3 Earlier bad letter detection | ||||||
|    the process to avoid doing a resolve and connect in vain. |  | ||||||
|  |  | ||||||
|  * REST fix for servers not behaving well on >2GB requests. This should fail |  Make the detection of (bad) %0d and %0a codes in FTP url parts earlier in the | ||||||
|    if the server doesn't set the pointer to the requested index. The tricky |  process to avoid doing a resolve and connect in vain. | ||||||
|    (impossible?) part is to figure out if the server did the right thing or |  | ||||||
|    not. |  | ||||||
|  |  | ||||||
|  * Support the most common FTP proxies, Philip Newton provided a list | 4.4 REST for large files | ||||||
|    allegedly from ncftp: |  | ||||||
|    http://curl.haxx.se/mail/archive-2003-04/0126.html |  | ||||||
|  |  | ||||||
|  * Make CURLOPT_FTPPORT support an additional port number on the IP/if/name, |  REST fix for servers not behaving well on >2GB requests. This should fail if | ||||||
|  |  the server doesn't set the pointer to the requested index. The tricky | ||||||
|  |  (impossible?) part is to figure out if the server did the right thing or not. | ||||||
|  |  | ||||||
|  | 4.5 FTP proxy support | ||||||
|  |  | ||||||
|  |  Support the most common FTP proxies, Philip Newton provided a list allegedly | ||||||
|  |  from ncftp. This is not a subject without debate, and is probably not really | ||||||
|  |  suitable for libcurl.  http://curl.haxx.se/mail/archive-2003-04/0126.html | ||||||
|  |  | ||||||
|  | 4.6 PORT port range | ||||||
|  |  | ||||||
|  |  Make CURLOPT_FTPPORT support an additional port number on the IP/if/name, | ||||||
|  like "blabla:[port]" or possibly even "blabla:[portfirst]-[portsecond]". |  like "blabla:[port]" or possibly even "blabla:[portfirst]-[portsecond]". | ||||||
|  http://curl.haxx.se/bug/feature.cgi?id=1505166 |  http://curl.haxx.se/bug/feature.cgi?id=1505166 | ||||||
|  |  | ||||||
|  * FTP ASCII transfers do not follow RFC959. They don't convert the data | 4.7 ASCII support | ||||||
|  |  | ||||||
|  |  FTP ASCII transfers do not follow RFC959. They don't convert the data | ||||||
|  accordingly. |  accordingly. | ||||||
|  |  | ||||||
|  * Since USERPWD always override the user and password specified in URLs, we | 5. HTTP | ||||||
|    might need another way to specify user+password for anonymous ftp logins. |  | ||||||
|  |  | ||||||
|  * The FTP code should get a way of returning errors that is known to still | 5.1 Other HTTP versions with CONNECT | ||||||
|    have the control connection alive and sound. Currently, a returned error |  | ||||||
|    from within ftp-functions does not tell if the control connection is still |  | ||||||
|    OK to use or not. This causes libcurl to fail to re-use connections |  | ||||||
|    slightly too often. |  | ||||||
|  |  | ||||||
|  HTTP |  When doing CONNECT to a HTTP proxy, libcurl always uses HTTP/1.0. This has | ||||||
|  |  never been reported as causing trouble to anyone, but should be considered to | ||||||
|  |  use the HTTP version the user has chosen. | ||||||
|  |  | ||||||
|  * When doing CONNECT to a HTTP proxy, libcurl always uses HTTP/1.0. This has | 5.2 Better persistancy for HTTP 1.0 | ||||||
|    never been reported as causing trouble to anyone, but should be considered |  | ||||||
|    to use the HTTP version the user has chosen. |  | ||||||
|  |  | ||||||
|  * "Better" support for persistent connections over HTTP 1.0 |  "Better" support for persistent connections over HTTP 1.0 | ||||||
|  http://curl.haxx.se/bug/feature.cgi?id=1089001 |  http://curl.haxx.se/bug/feature.cgi?id=1089001 | ||||||
|  |  | ||||||
|  TELNET | 5.3 support FF3 sqlite cookie files | ||||||
|  |  | ||||||
|  * Reading input (to send to the remote server) on stdin is a crappy solution |  Firefox 3 is changing from its former format to a a sqlite database instead. | ||||||
|    for library purposes. We need to invent a good way for the application to |  We should consider how (lib)curl can/should support this. | ||||||
|    be able to provide the data to send. |  http://curl.haxx.se/bug/feature.cgi?id=1871388 | ||||||
|  |  | ||||||
|  * Move the telnet support's network select() loop go away and merge the code | 6. TELNET | ||||||
|  |  | ||||||
|  | 6.1 ditch stdin | ||||||
|  |  | ||||||
|  | Reading input (to send to the remote server) on stdin is a crappy solution for | ||||||
|  | library purposes. We need to invent a good way for the application to be able | ||||||
|  | to provide the data to send. | ||||||
|  |  | ||||||
|  | 6.2 ditch telnet-specific select | ||||||
|  |  | ||||||
|  |  Move the telnet support's network select() loop go away and merge the code | ||||||
|  into the main transfer loop. Until this is done, the multi interface won't |  into the main transfer loop. Until this is done, the multi interface won't | ||||||
|  work for telnet. |  work for telnet. | ||||||
|  |  | ||||||
|  SSL | 7. SSL | ||||||
|  |  | ||||||
|  * Provide an option that allows for disabling specific SSL versions, such as | 7.1 Disable specific versions | ||||||
|  |  | ||||||
|  |  Provide an option that allows for disabling specific SSL versions, such as | ||||||
|  SSLv2 http://curl.haxx.se/bug/feature.cgi?id=1767276 |  SSLv2 http://curl.haxx.se/bug/feature.cgi?id=1767276 | ||||||
|  |  | ||||||
|  * Provide a libcurl API for setting mutex callbacks in the underlying SSL | 7.2 Provide mytex locking API | ||||||
|  |  | ||||||
|  |  Provide a libcurl API for setting mutex callbacks in the underlying SSL | ||||||
|  library, so that the same application code can use mutex-locking |  library, so that the same application code can use mutex-locking | ||||||
|  independently of OpenSSL or GnutTLS being used. |  independently of OpenSSL or GnutTLS being used. | ||||||
|  |  | ||||||
|  * Anton Fedorov's "dumpcert" patch: | 7.3 dumpcert | ||||||
|  |  | ||||||
|  |  Anton Fedorov's "dumpcert" patch: | ||||||
|  http://curl.haxx.se/mail/lib-2004-03/0088.html |  http://curl.haxx.se/mail/lib-2004-03/0088.html | ||||||
|  |  | ||||||
|  * Evaluate/apply Gertjan van Wingerde's SSL patches: | 7.4 Evaluate SSL patches | ||||||
|  |  | ||||||
|  |  Evaluate/apply Gertjan van Wingerde's SSL patches: | ||||||
|  http://curl.haxx.se/mail/lib-2004-03/0087.html |  http://curl.haxx.se/mail/lib-2004-03/0087.html | ||||||
|  |  | ||||||
|  * "Look at SSL cafile - quick traces look to me like these are done on every | 7.5 Cache OpenSSL contexts | ||||||
|    request as well, when they should only be necessary once per ssl context |  | ||||||
|    (or once per handle)". The major improvement we can rather easily do is to |  | ||||||
|    make sure we don't create and kill a new SSL "context" for every request, |  | ||||||
|    but instead make one for every connection and re-use that SSL context in |  | ||||||
|    the same style connections are re-used. It will make us use slightly more |  | ||||||
|    memory but it will libcurl do less creations and deletions of SSL contexts. |  | ||||||
|  |  | ||||||
|  * Add an interface to libcurl that enables "session IDs" to get |  "Look at SSL cafile - quick traces look to me like these are done on every | ||||||
|  |  request as well, when they should only be necessary once per ssl context (or | ||||||
|  |  once per handle)". The major improvement we can rather easily do is to make | ||||||
|  |  sure we don't create and kill a new SSL "context" for every request, but | ||||||
|  |  instead make one for every connection and re-use that SSL context in the same | ||||||
|  |  style connections are re-used. It will make us use slightly more memory but | ||||||
|  |  it will libcurl do less creations and deletions of SSL contexts. | ||||||
|  |  | ||||||
|  | 7.6 Export session ids | ||||||
|  |  | ||||||
|  |  Add an interface to libcurl that enables "session IDs" to get | ||||||
|  exported/imported. Cris Bailiff said: "OpenSSL has functions which can |  exported/imported. Cris Bailiff said: "OpenSSL has functions which can | ||||||
|    serialise the current SSL state to a buffer of your choice, and |  serialise the current SSL state to a buffer of your choice, and recover/reset | ||||||
|    recover/reset the state from such a buffer at a later date - this is used |  the state from such a buffer at a later date - this is used by mod_ssl for | ||||||
|    by mod_ssl for apache to implement and SSL session ID cache". |  apache to implement and SSL session ID cache". | ||||||
|  |  | ||||||
|  * OpenSSL supports a callback for customised verification of the peer | 7.7 Provide callback for cert verfication | ||||||
|  |  | ||||||
|  |  OpenSSL supports a callback for customised verification of the peer | ||||||
|  certificate, but this doesn't seem to be exposed in the libcurl APIs. Could |  certificate, but this doesn't seem to be exposed in the libcurl APIs. Could | ||||||
|    it be? There's so much that could be done if it were! (brought by Chris |  it be? There's so much that could be done if it were! | ||||||
|    Clark) |  | ||||||
|  |  | ||||||
|  * Make curl's SSL layer capable of using other free SSL libraries.  Such as | 7.8 Support other SSL libraries | ||||||
|  |  | ||||||
|  |  Make curl's SSL layer capable of using other free SSL libraries.  Such as | ||||||
|  MatrixSSL (http://www.matrixssl.org/). |  MatrixSSL (http://www.matrixssl.org/). | ||||||
|  |  | ||||||
|  * Peter Sylvester's patch for SRP on the TLS layer. | 7.9  Support SRP on the TLS layer | ||||||
|    Awaits OpenSSL support for this, no need to support this in libcurl before |  | ||||||
|    there's an OpenSSL release that does it. |  | ||||||
|  |  | ||||||
|  * make the configure --with-ssl option first check for OpenSSL, then GnuTLS, |  Peter Sylvester's patch for SRP on the TLS layer.  Awaits OpenSSL support for | ||||||
|  |  this, no need to support this in libcurl before there's an OpenSSL release | ||||||
|  |  that does it. | ||||||
|  |  | ||||||
|  | 7.10 improve configure --with-ssl | ||||||
|  |  | ||||||
|  |  make the configure --with-ssl option first check for OpenSSL, then GnuTLS, | ||||||
|  then NSS... |  then NSS... | ||||||
|  |  | ||||||
|  GnuTLS | 8. GnuTLS | ||||||
|  |  | ||||||
|  * Get NTLM working using the functions provided by libgcrypt, since GnuTLS | 8.1 Make NTLM work without OpenSSL functions | ||||||
|  |  | ||||||
|  |  Get NTLM working using the functions provided by libgcrypt, since GnuTLS | ||||||
|  already depends on that to function. Not strictly SSL/TLS related, but |  already depends on that to function. Not strictly SSL/TLS related, but | ||||||
|  hey... Another option is to get available DES and MD4 source code from the |  hey... Another option is to get available DES and MD4 source code from the | ||||||
|  cryptopp library. They are fine license-wise, but are C++. |  cryptopp library. They are fine license-wise, but are C++. | ||||||
|  |  | ||||||
|  * SSL engine stuff? | 8.2 SSl engine stuff | ||||||
|  |  | ||||||
|  * Work out a common method with Peter Sylvester's OpenSSL-patch for SRP |  Is this even possible? | ||||||
|    on the TLS to provide name and password |  | ||||||
|  |  | ||||||
|  * Fix the connection phase to be non-blocking when multi interface is used | 8.3 SRP | ||||||
|  |  | ||||||
|  * Add a way to check if the connection seems to be alive, to correspond to |  Work out a common method with Peter Sylvester's OpenSSL-patch for SRP on the | ||||||
|    the SSL_peak() way we use with OpenSSL. |  TLS to provide name and password. GnuTLS already supports it... | ||||||
|  |  | ||||||
|  LDAP | 8.4 non-blocking | ||||||
|  |  | ||||||
|  |  Fix the connection phase to be non-blocking when multi interface is used | ||||||
|  |  | ||||||
|  | 8.5 check connection | ||||||
|  |  | ||||||
|  |  Add a way to check if the connection seems to be alive, to correspond to the | ||||||
|  |  SSL_peak() way we use with OpenSSL. | ||||||
|  |  | ||||||
|  | 9. LDAP | ||||||
|  |  | ||||||
|  | 9.1 ditch ldap-specific select | ||||||
|  |  | ||||||
|  * Look over the implementation. The looping will have to "go away" from the |  * Look over the implementation. The looping will have to "go away" from the | ||||||
|    lib/ldap.c source file and get moved to the main network code so that the |    lib/ldap.c source file and get moved to the main network code so that the | ||||||
|    multi interface and friends will work for LDAP as well. |    multi interface and friends will work for LDAP as well. | ||||||
|  |  | ||||||
|  NEW PROTOCOLS | 10. New protocols | ||||||
|  |  | ||||||
|  * RTSP - RFC2326 (protocol - very HTTP-like, also contains URL description) | 10.1 RTSP | ||||||
|  |  | ||||||
|  * RSYNC (no RFCs for protocol nor URI/URL format).  An implementation should |  RFC2326 (protocol - very HTTP-like, also contains URL description) | ||||||
|  |  | ||||||
|  | 10.2 RSYNC | ||||||
|  |  | ||||||
|  |  There's no RFC for protocol nor URI/URL format.  An implementation should | ||||||
|  most probably use an existing rsync library, such as librsync. |  most probably use an existing rsync library, such as librsync. | ||||||
|  |  | ||||||
|  CLIENT | 10.3 RTMP | ||||||
|  |  | ||||||
|  * Add option that is similar to -O but that takes the output file name from |  There exists a patch that claims to introduce this protocol: | ||||||
|    the Content-Disposition: header, and/or uses the local file name used in |  http://osdir.com/ml/gnu.gnash.devel2/2006-11/msg00278.html, further details | ||||||
|  |  in the feature-request: http://curl.haxx.se/bug/feature.cgi?id=1843469 | ||||||
|  |  | ||||||
|  | 11. Client | ||||||
|  |  | ||||||
|  | 11.1 Content-Disposition | ||||||
|  |  | ||||||
|  |  Add option that is similar to -O but that takes the output file name from the | ||||||
|  |  Content-Disposition: header, and/or uses the local file name used in | ||||||
|  redirections for the cases the server bounces the request further to a |  redirections for the cases the server bounces the request further to a | ||||||
|  different file (name): http://curl.haxx.se/bug/feature.cgi?id=1364676 |  different file (name): http://curl.haxx.se/bug/feature.cgi?id=1364676 | ||||||
|  |  | ||||||
|  * "curl --sync http://example.com/feed[1-100].rss" or | 11.2 sync | ||||||
|  |  | ||||||
|  |  "curl --sync http://example.com/feed[1-100].rss" or | ||||||
|  "curl --sync http://example.net/{index,calendar,history}.html" |  "curl --sync http://example.net/{index,calendar,history}.html" | ||||||
|  |  | ||||||
|  Downloads a range or set of URLs using the remote name, but only if the |  Downloads a range or set of URLs using the remote name, but only if the | ||||||
|  remote file is newer than the local file. A Last-Modified HTTP date header |  remote file is newer than the local file. A Last-Modified HTTP date header | ||||||
|  should also be used to set the mod date on the downloaded file. |  should also be used to set the mod date on the downloaded file. | ||||||
|    (idea from "Brianiac") |  | ||||||
|  |  | ||||||
|  * Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'. | 11.3 glob posts | ||||||
|    Requested by Dane Jensen and others. This is easily scripted though. |  | ||||||
|  |  | ||||||
|  * Add an option that prevents cURL from overwriting existing local files. When |  Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'. | ||||||
|  |  This is easily scripted though. | ||||||
|  |  | ||||||
|  | 11.4 prevent file overwriting | ||||||
|  |  | ||||||
|  |  Add an option that prevents cURL from overwriting existing local files. When | ||||||
|  used, and there already is an existing file with the target file name |  used, and there already is an existing file with the target file name | ||||||
|  (either -O or -o), a number should be appended (and increased if already |  (either -O or -o), a number should be appended (and increased if already | ||||||
|  existing). So that index.html becomes first index.html.1 and then |  existing). So that index.html becomes first index.html.1 and then | ||||||
|    index.html.2 etc. Jeff Pohlmeyer suggested. |  index.html.2 etc. | ||||||
|  |  | ||||||
|  * "curl ftp://site.com/*.txt" | 11.5 ftp wildcard download | ||||||
|  |  | ||||||
|  * The client could be told to use maximum N simultaneous parallel transfers |  "curl ftp://site.com/*.txt" | ||||||
|    and then just make sure that happens. It should of course not make more |  | ||||||
|    than one connection to the same remote host. This would require the client |  | ||||||
|    to use the multi interface. http://curl.haxx.se/bug/feature.cgi?id=1558595 |  | ||||||
|  |  | ||||||
|  * Extending the capabilities of the multipart formposting. How about leaving | 11.6 simultaneous parallel transfers | ||||||
|  |  | ||||||
|  |  The client could be told to use maximum N simultaneous parallel transfers and | ||||||
|  |  then just make sure that happens. It should of course not make more than one | ||||||
|  |  connection to the same remote host. This would require the client to use the | ||||||
|  |  multi interface. http://curl.haxx.se/bug/feature.cgi?id=1558595 | ||||||
|  |  | ||||||
|  | 11.7 provide formpost headers | ||||||
|  |  | ||||||
|  |  Extending the capabilities of the multipart formposting. How about leaving | ||||||
|  the ';type=foo' syntax as it is and adding an extra tag (headers) which |  the ';type=foo' syntax as it is and adding an extra tag (headers) which | ||||||
|  works like this: curl -F "coolfiles=@fil1.txt;headers=@fil1.hdr" where |  works like this: curl -F "coolfiles=@fil1.txt;headers=@fil1.hdr" where | ||||||
|  fil1.hdr contains extra headers like |  fil1.hdr contains extra headers like | ||||||
| @@ -264,17 +452,11 @@ TODO | |||||||
|    X-User-Comment: Please don't use browser specific HTML code |    X-User-Comment: Please don't use browser specific HTML code | ||||||
|  |  | ||||||
|  which should overwrite the program reasonable defaults (plain/text, |  which should overwrite the program reasonable defaults (plain/text, | ||||||
|    8bit...) (Idea brough to us by kromJx) |  8bit...) | ||||||
|  |  | ||||||
|  * ability to specify the classic computing suffixes on the range | 11.8 url-specific options | ||||||
|    specifications. For example, to download the first 500 Kilobytes of a file, |  | ||||||
|    be able to specify the following for the -r option: "-r 0-500K" or for the |  | ||||||
|    first 2 Megabytes of a file: "-r 0-2M". (Mark Smith suggested) |  | ||||||
|  |  | ||||||
|  * --data-encode that URL encodes the data before posting |  Provide a way to make options bound to a specific URL among several on the | ||||||
|    http://curl.haxx.se/mail/archive-2003-11/0091.html (Kevin Roth suggested) |  | ||||||
|  |  | ||||||
|  * Provide a way to make options bound to a specific URL among several on the |  | ||||||
|  command line. Possibly by letting ':' separate options between URLs, |  command line. Possibly by letting ':' separate options between URLs, | ||||||
|  similar to this: |  similar to this: | ||||||
|  |  | ||||||
| @@ -286,32 +468,46 @@ TODO | |||||||
|  |  | ||||||
|  The example would do a POST-GET-POST combination on a single command line. |  The example would do a POST-GET-POST combination on a single command line. | ||||||
|  |  | ||||||
|  BUILD | 12. Build | ||||||
|  |  | ||||||
|  * Consider extending 'roffit' to produce decent ASCII output, and use that | 12.1 roffit | ||||||
|  |  | ||||||
|  |  Consider extending 'roffit' to produce decent ASCII output, and use that | ||||||
|  instead of (g)nroff when building src/hugehelp.c |  instead of (g)nroff when building src/hugehelp.c | ||||||
|  |  | ||||||
|  TEST SUITE | 13. Test suite | ||||||
|  |  | ||||||
|  * Make our own version of stunnel for simple port forwarding to enable HTTPS | 13.1 SSL tunnel | ||||||
|  |  | ||||||
|  |  Make our own version of stunnel for simple port forwarding to enable HTTPS | ||||||
|  and FTP-SSL tests without the stunnel dependency, and it could allow us to |  and FTP-SSL tests without the stunnel dependency, and it could allow us to | ||||||
|  provide test tools built with either OpenSSL or GnuTLS |  provide test tools built with either OpenSSL or GnuTLS | ||||||
|  |  | ||||||
|  * If perl wasn't found by the configure script, don't attempt to run the | 13.2 nicer lacking perl message | ||||||
|    tests but explain something nice why it doesn't. |  | ||||||
|  |  | ||||||
|  * Extend the test suite to include more protocols. The telnet could just do |  If perl wasn't found by the configure script, don't attempt to run the tests | ||||||
|    ftp or http operations (for which we have test servers). |  but explain something nice why it doesn't. | ||||||
|  |  | ||||||
|  * Make the test suite work on more platforms. OpenBSD and Mac OS. Remove | 13.3 more protocols supported | ||||||
|  |  | ||||||
|  |  Extend the test suite to include more protocols. The telnet could just do ftp | ||||||
|  |  or http operations (for which we have test servers). | ||||||
|  |  | ||||||
|  | 13.4 more platforms supported | ||||||
|  |  | ||||||
|  |  Make the test suite work on more platforms. OpenBSD and Mac OS. Remove | ||||||
|  fork()s and it should become even more portable. |  fork()s and it should become even more portable. | ||||||
|  |  | ||||||
|  NEXT soname bump | 14. Next SONAME bump | ||||||
|  |  | ||||||
|  * #undef CURL_FTP_HTTPSTYLE_HEAD in lib/ftp.c to remove the HTTP-style headers | 14.1 http-style HEAD output for ftp | ||||||
|  |  | ||||||
|  |  #undef CURL_FTP_HTTPSTYLE_HEAD in lib/ftp.c to remove the HTTP-style headers | ||||||
|  from being output in NOBODY requests over ftp |  from being output in NOBODY requests over ftp | ||||||
|  |  | ||||||
|  * Combine some of the error codes to remove duplicates.  The original | 14.2 combine error codes | ||||||
|  |  | ||||||
|  |  Combine some of the error codes to remove duplicates.  The original | ||||||
|  numbering should not be changed, and the old identifiers would be |  numbering should not be changed, and the old identifiers would be | ||||||
|  macroed to the new ones in an CURL_NO_OLDIES section to help with |  macroed to the new ones in an CURL_NO_OLDIES section to help with | ||||||
|  backward compatibility. |  backward compatibility. | ||||||
| @@ -327,23 +523,50 @@ TODO | |||||||
|     CURLE_TFTP_NOTFOUND => CURLE_REMOTE_FILE_NOT_FOUND |     CURLE_TFTP_NOTFOUND => CURLE_REMOTE_FILE_NOT_FOUND | ||||||
|     CURLE_TFTP_PERM => CURLE_REMOTE_ACCESS_DENIED |     CURLE_TFTP_PERM => CURLE_REMOTE_ACCESS_DENIED | ||||||
|  |  | ||||||
|  NEXT MAJOR RELEASE | 14.3 extend CURLOPT_SOCKOPTFUNCTION prototype | ||||||
|  |  | ||||||
|  * curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a |  The current prototype only provides 'purpose' that tells what the | ||||||
|  |  connection/socket is for, but not any protocol or similar. It makes it hard | ||||||
|  |  for applications to differentiate on TCP vs UDP and even HTTP vs FTP and | ||||||
|  |  similar. | ||||||
|  |  | ||||||
|  | 15. Next major release | ||||||
|  |  | ||||||
|  | 15.1 cleanup return codes | ||||||
|  |  | ||||||
|  |  curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a | ||||||
|  CURLMcode. These should be changed to be the same. |  CURLMcode. These should be changed to be the same. | ||||||
|  |  | ||||||
|  * remove obsolete defines from curl/curl.h | 15.2 remove obsolete defines | ||||||
|  |  | ||||||
|  * make several functions use size_t instead of int in their APIs |  remove obsolete defines from curl/curl.h | ||||||
|  |  | ||||||
|  | 15.3 size_t | ||||||
|  |  | ||||||
|  |  make several functions use size_t instead of int in their APIs | ||||||
|  |  | ||||||
|  | 15.4 remove several functions | ||||||
|  |  | ||||||
|  |  remove the following functions from the public API: | ||||||
|  |  | ||||||
|  * remove the following functions from the public API: |  | ||||||
|  curl_getenv |  curl_getenv | ||||||
|  |  | ||||||
|  curl_mprintf (and variations) |  curl_mprintf (and variations) | ||||||
|  |  | ||||||
|  curl_strequal |  curl_strequal | ||||||
|  |  | ||||||
|  curl_strnequal |  curl_strnequal | ||||||
|  |  | ||||||
|  They will instead become curlx_ - alternatives. That makes the curl app |  They will instead become curlx_ - alternatives. That makes the curl app | ||||||
|  still capable of building with them from source. |  still capable of building with them from source. | ||||||
|  |  | ||||||
|  * Remove support for CURLOPT_FAILONERROR, it has gotten too kludgy and weird | 15.5 remove CURLOPT_FAILONERROR | ||||||
|  |  | ||||||
|  |  Remove support for CURLOPT_FAILONERROR, it has gotten too kludgy and weird | ||||||
|  internally. Let the app judge success or not for itself. |  internally. Let the app judge success or not for itself. | ||||||
|  |  | ||||||
|  | 15.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE | ||||||
|  |  | ||||||
|  |  Remove support for a global DNS cache. Anything global is silly, and we | ||||||
|  |  already offer the share interface for the same functionality but done | ||||||
|  |  "right". | ||||||
|   | |||||||
							
								
								
									
										154
									
								
								docs/curl.1
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								docs/curl.1
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2008, 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,7 +21,7 @@ | |||||||
| .\" * $Id$ | .\" * $Id$ | ||||||
| .\" ************************************************************************** | .\" ************************************************************************** | ||||||
| .\" | .\" | ||||||
| .TH curl 1 "21 Sep 2007" "Curl 7.17.1" "Curl Manual" | .TH curl 1 "5 Jan 2008" "Curl 7.18.0" "Curl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl \- transfer a URL | curl \- transfer a URL | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -82,7 +82,7 @@ specified on a single command line and cannot be used between separate curl | |||||||
| invokes. | invokes. | ||||||
| .SH "PROGRESS METER" | .SH "PROGRESS METER" | ||||||
| curl normally displays a progress meter during operations, indicating amount | curl normally displays a progress meter during operations, indicating amount | ||||||
| of transfered data, transfer speeds and estimated time left etc. | of transferred data, transfer speeds and estimated time left etc. | ||||||
|  |  | ||||||
| However, since curl displays data to the terminal by default, if you invoke | However, since curl displays data to the terminal by default, if you invoke | ||||||
| curl to do an operation and it is about to write data to the terminal, it | curl to do an operation and it is about to write data to the terminal, it | ||||||
| @@ -115,10 +115,10 @@ used. | |||||||
| .IP "--anyauth" | .IP "--anyauth" | ||||||
| (HTTP) Tells curl to figure out authentication method by itself, and use the | (HTTP) Tells curl to figure out authentication method by itself, and use the | ||||||
| most secure one the remote site claims it supports. This is done by first | most secure one the remote site claims it supports. This is done by first | ||||||
| doing a request and checking the response-headers, thus inducing an extra | doing a request and checking the response-headers, thus possibly inducing an | ||||||
| network round-trip. This is used instead of setting a specific authentication | extra network round-trip. This is used instead of setting a specific | ||||||
| method, which you can do with \fI--basic\fP, \fI--digest\fP, \fI--ntlm\fP, and | authentication method, which you can do with \fI--basic\fP, \fI--digest\fP, | ||||||
| \fI--negotiate\fP. | \fI--ntlm\fP, and \fI--negotiate\fP. | ||||||
|  |  | ||||||
| Note that using --anyauth is not recommended if you do uploads from stdin, | Note that using --anyauth is not recommended if you do uploads from stdin, | ||||||
| since it may require data to be sent twice and then the client must be able to | since it may require data to be sent twice and then the client must be able to | ||||||
| @@ -224,43 +224,63 @@ To create remote directories when using FTP or SFTP, try | |||||||
| If this option is used several times, the following occurrences make no | If this option is used several times, the following occurrences make no | ||||||
| difference. | difference. | ||||||
| .IP "-d/--data <data>" | .IP "-d/--data <data>" | ||||||
| (HTTP) Sends the specified data in a POST request to the HTTP server, in a way | (HTTP) Sends the specified data in a POST request to the HTTP server, in the | ||||||
| that can emulate as if a user has filled in a HTML form and pressed the submit | same way that a browser does when a user has filled in an HTML form and | ||||||
| button. Note that the data is sent exactly as specified with no extra | presses the submit button. This will cause curl to pass the data to the server | ||||||
| processing (with all newlines cut off).  The data is expected to be | using the content-type application/x-www-form-urlencoded.  Compare to | ||||||
| \&"url-encoded". This will cause curl to pass the data to the server using the | \fI-F/--form\fP. | ||||||
| content-type application/x-www-form-urlencoded. Compare to \fI-F/--form\fP. If |  | ||||||
| this option is used more than once on the same command line, the data pieces | \fI-d/--data\fP is the same as \fI--data-ascii\fP. To post data purely binary, | ||||||
| specified will be merged together with a separating &-letter. Thus, using '-d | you should instead use the \fI--data-binary\fP option. To URL encode the value | ||||||
| name=daniel -d skill=lousy' would generate a post chunk that looks like | of a form field you may use \fI--data-urlencode\fP. | ||||||
| \&'name=daniel&skill=lousy'. |  | ||||||
|  | If any of these options is used more than once on the same command line, the | ||||||
|  | data pieces specified will be merged together with a separating | ||||||
|  | &-letter. Thus, using '-d name=daniel -d skill=lousy' would generate a post | ||||||
|  | chunk that looks like \&'name=daniel&skill=lousy'. | ||||||
|  |  | ||||||
| If you start the data with the letter @, the rest should be a file name to | 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\fP @foobar". | \fI--data @foobar\fP. | ||||||
|  |  | ||||||
| To post data purely binary, you should instead use the \fI--data-binary\fP |  | ||||||
| option. |  | ||||||
|  |  | ||||||
| \fI-d/--data\fP is the same as \fI--data-ascii\fP. |  | ||||||
|  |  | ||||||
| If this option is used several times, the ones following the first will |  | ||||||
| append data. |  | ||||||
| .IP "--data-ascii <data>" |  | ||||||
| (HTTP) This is an alias for the \fI-d/--data\fP option. |  | ||||||
|  |  | ||||||
| If this option is used several times, the ones following the first will |  | ||||||
| append data. |  | ||||||
| .IP "--data-binary <data>" | .IP "--data-binary <data>" | ||||||
| (HTTP) This posts data in a similar manner as \fI--data-ascii\fP does, | (HTTP) This posts data exactly as specified with no extra processing | ||||||
| although when using this option the entire context of the posted data is kept | whatsoever. | ||||||
| as-is. If you want to post a binary file without the strip-newlines feature of |  | ||||||
| the \fI--data-ascii\fP option, this is for you. |  | ||||||
|  |  | ||||||
| If this option is used several times, the ones following the first will | If you start the data with the letter @, the rest should be a filename.  Data | ||||||
| append data. | is posted in a similar manner as \fI--data-ascii\fP does, except that newlines | ||||||
|  | are preserved and conversions are never done. | ||||||
|  |  | ||||||
|  | If this option is used several times, the ones following the first will append | ||||||
|  | data. As described in \fI-d/--data\fP. | ||||||
|  | .IP "--data-urlencode <data>" | ||||||
|  | (HTTP) This posts data, similar to the other --data options with the exception | ||||||
|  | that this performs URL encoding. (Added in 7.18.0) | ||||||
|  |  | ||||||
|  | To be CGI compliant, the <data> part should begin with a \fIname\fP followed | ||||||
|  | by a separator and a content specification. The <data> part can be passed to | ||||||
|  | curl using one of the following syntaxes: | ||||||
|  | .RS | ||||||
|  | .IP "content" | ||||||
|  | This will make curl URL encode the content and pass that on. Just be careful | ||||||
|  | so that the content doesn't contain any = or @ letters, as that will then make | ||||||
|  | the syntax match one of the other cases below! | ||||||
|  | .IP "=content" | ||||||
|  | This will make curl URL encode the content and pass that on. The preceding = | ||||||
|  | letter is not included in the data. | ||||||
|  | .IP "name=content" | ||||||
|  | This will make curl URL encode the content part and pass that on. Note that | ||||||
|  | the name part is expected to be URL encoded already. | ||||||
|  | .IP "@filename" | ||||||
|  | This will make curl load data from the given file (including any newlines), | ||||||
|  | URL encode that data and pass it on in the POST. | ||||||
|  | .IP "name@filename" | ||||||
|  | This will make curl load data from the given file (including any newlines), | ||||||
|  | URL encode that data and pass it on in the POST. The name part gets an equal | ||||||
|  | sign appended, resulting in \fIname=urlencoded-file-content\fP. Note that the | ||||||
|  | name is expected to be URL encoded already. | ||||||
|  | .RE | ||||||
| .IP "--digest" | .IP "--digest" | ||||||
| (HTTP) Enables HTTP Digest authentication. This is a authentication that | (HTTP) Enables HTTP Digest authentication. This is a authentication that | ||||||
| prevents the password from being sent over the wire in clear text. Use this in | prevents the password from being sent over the wire in clear text. Use this in | ||||||
| @@ -546,7 +566,7 @@ See also the \fI-A/--user-agent\fP and \fI-e/--referer\fP options. | |||||||
| This option can be used multiple times to add/replace/remove multiple headers. | This option can be used multiple times to add/replace/remove multiple headers. | ||||||
| .IP "--hostpubmd5" | .IP "--hostpubmd5" | ||||||
| Pass a string containing 32 hexadecimal digits. The string should be the 128 | Pass a string containing 32 hexadecimal digits. The string should be the 128 | ||||||
| bit MD5 cheksum of the remote host's public key, curl will refuse the | bit MD5 checksum of the remote host's public key, curl will refuse the | ||||||
| connection with the host unless the md5sums match. This option is only for SCP | connection with the host unless the md5sums match. This option is only for SCP | ||||||
| and SFTP transfers. (Added in 7.17.1) | and SFTP transfers. (Added in 7.17.1) | ||||||
| .IP "--ignore-content-length" | .IP "--ignore-content-length" | ||||||
| @@ -592,6 +612,14 @@ See this online resource for further details: | |||||||
| \fBhttp://curl.haxx.se/docs/sslcerts.html\fP | \fBhttp://curl.haxx.se/docs/sslcerts.html\fP | ||||||
|  |  | ||||||
| If this option is used twice, the second time will again disable it. | If this option is used twice, the second time will again disable it. | ||||||
|  | .IP "--keepalive-time <seconds>" | ||||||
|  | This option sets the time a connection needs to remain idle before sending | ||||||
|  | keepalive probes and the time between individual keepalive probes. It is | ||||||
|  | currently effective on operating systems offering the TCP_KEEPIDLE and | ||||||
|  | TCP_KEEPINTVL socket options (meaning Linux, recent AIX, HP-UX and more). This | ||||||
|  | option has no effect if \fI--no-keepalive\fP is used. (Added in 7.18.0) | ||||||
|  |  | ||||||
|  | If this option is used multiple times, the last occurrence sets the amount. | ||||||
| .IP "--key <key>" | .IP "--key <key>" | ||||||
| (SSL/SSH) Private key file name. Allows you to provide your private key in this | (SSL/SSH) Private key file name. Allows you to provide your private key in this | ||||||
| separate file. | separate file. | ||||||
| @@ -617,8 +645,12 @@ If this option is used several times, the last one will be used. | |||||||
| Specify which config file to read curl arguments from. The config file is a | Specify which config file to read curl arguments from. The config file is a | ||||||
| text file in which command line arguments can be written which then will be | text file in which command line arguments can be written which then will be | ||||||
| used as if they were written on the actual command line. Options and their | used as if they were written on the actual command line. Options and their | ||||||
| parameters must be specified on the same config file line. If the parameter is | parameters must be specified on the same config file line, separated by | ||||||
| to contain white spaces, the parameter must be enclosed within quotes.  If the | white space, colon, the equals sign or any combination thereof (however, | ||||||
|  | the preferred separator is the equals sign). If the parameter is to contain | ||||||
|  | white spaces, the parameter must be enclosed within quotes. Within double | ||||||
|  | quotes, the following escape sequences are available: \\\\, \\", \\t, \\n, | ||||||
|  | \\r and \\v. A backlash preceding any other letter is  ignored. If the | ||||||
| first column of a config line is a '#' character, the rest of the line will be | first column of a config line is a '#' character, the rest of the line will be | ||||||
| treated as a comment. Only write one option per physical line in the config | treated as a comment. Only write one option per physical line in the config | ||||||
| file. | file. | ||||||
| @@ -673,7 +705,8 @@ NOTE: this does not properly support -F and the sending of multipart | |||||||
| formposts, so in those cases the output program will be missing necessary | formposts, so in those cases the output program will be missing necessary | ||||||
| calls to \fIcurl_formadd(3)\fP, and possibly more. | calls to \fIcurl_formadd(3)\fP, and possibly more. | ||||||
|  |  | ||||||
| If this option is used several times, the last given file name will be used. | If this option is used several times, the last given file name will be | ||||||
|  | used. (Added in 7.16.1) | ||||||
| .IP "--limit-rate <speed>" | .IP "--limit-rate <speed>" | ||||||
| Specify the maximum transfer rate you want curl to use. This feature is useful | Specify the maximum transfer rate you want curl to use. This feature is useful | ||||||
| if you have a limited pipe and you'd like your transfer not use your entire | if you have a limited pipe and you'd like your transfer not use your entire | ||||||
| @@ -799,6 +832,11 @@ will output the data in chunks, not necessarily exactly when the data arrives. | |||||||
| Using this option will disable that buffering. | Using this option will disable that buffering. | ||||||
|  |  | ||||||
| If this option is used twice, the second will again switch on buffering. | If this option is used twice, the second will again switch on buffering. | ||||||
|  | .IP "--no-keepalive" | ||||||
|  | Disables the use of keepalive messages on the TCP connection, as by default | ||||||
|  | curl enables them. | ||||||
|  |  | ||||||
|  | If this option is used twice, the second will again enable keepalive. | ||||||
| .IP "--no-sessionid" | .IP "--no-sessionid" | ||||||
| (SSL) Disable curl's use of SSL session-ID caching.  By default all transfers | (SSL) Disable curl's use of SSL session-ID caching.  By default all transfers | ||||||
| are done using the cache. Note that while nothing ever should get hurt by | are done using the cache. Note that while nothing ever should get hurt by | ||||||
| @@ -861,7 +899,7 @@ a redirection. This option is meaningful only when using \fI-L/--location\fP | |||||||
| (Added in 7.17.1) | (Added in 7.17.1) | ||||||
| .IP "--proxy-anyauth" | .IP "--proxy-anyauth" | ||||||
| Tells curl to pick a suitable authentication method when communicating with | Tells curl to pick a suitable authentication method when communicating with | ||||||
| the given proxy. This will cause an extra request/response round-trip. (Added | the given proxy. This might cause an extra request/response round-trip. (Added | ||||||
| in 7.13.2) | in 7.13.2) | ||||||
|  |  | ||||||
| If this option is used twice, the second will again disable the proxy use-any | If this option is used twice, the second will again disable the proxy use-any | ||||||
| @@ -948,9 +986,9 @@ This option can be used multiple times. | |||||||
| random data. The data is used to seed the random engine for SSL connections. | random data. The data is used to seed the random engine for SSL connections. | ||||||
| See also the \fI--egd-file\fP option. | See also the \fI--egd-file\fP option. | ||||||
| .IP "-r/--range <range>" | .IP "-r/--range <range>" | ||||||
| (HTTP/FTP) | (HTTP/FTP/FILE) Retrieve a byte range (i.e a partial document) from a | ||||||
| Retrieve a byte range (i.e a partial document) from a HTTP/1.1 or FTP | HTTP/1.1, FTP server or a local FILE. Ranges can be specified in a number of | ||||||
| server. Ranges can be specified in a number of ways. | ways. | ||||||
| .RS | .RS | ||||||
| .TP 10 | .TP 10 | ||||||
| .B 0-499 | .B 0-499 | ||||||
| @@ -1049,9 +1087,28 @@ This option overrides any previous use of \fI-x/--proxy\fP, as they are | |||||||
| mutually exclusive. | mutually exclusive. | ||||||
|  |  | ||||||
| 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 "--socks4a <host[:port]>" | ||||||
|  | Use the specified SOCKS4a proxy. If the port number is not specified, it is | ||||||
|  | assumed at port 1080. (Added in 7.18.0) | ||||||
|  |  | ||||||
|  | This option overrides any previous use of \fI-x/--proxy\fP, as they are | ||||||
|  | mutually exclusive. | ||||||
|  |  | ||||||
|  | If this option is used several times, the last one will be used. | ||||||
|  | .IP "--socks5-hostname <host[:port]>" | ||||||
|  | Use the specified SOCKS5 proxy (and let the proxy resolve the host name). If | ||||||
|  | the port number is not specified, it is assumed at port 1080. (Added in | ||||||
|  | 7.18.0) | ||||||
|  |  | ||||||
|  | This option overrides any previous use of \fI-x/--proxy\fP, as they are | ||||||
|  | mutually exclusive. | ||||||
|  |  | ||||||
|  | If this option is used several times, the last one will be used. (This option | ||||||
|  | was previously wrongly documented and used as --socks without the number | ||||||
|  | appended.) | ||||||
| .IP "--socks5 <host[:port]>" | .IP "--socks5 <host[:port]>" | ||||||
| Use the specified SOCKS5 proxy. If the port number is not specified, it is | Use the specified SOCKS5 proxy - but resolve the host name locally. If the | ||||||
| assumed at port 1080. (Added in 7.11.1) | port number is not specified, it is assumed at port 1080. | ||||||
|  |  | ||||||
| This option overrides any previous use of \fI-x/--proxy\fP, as they are | This option overrides any previous use of \fI-x/--proxy\fP, as they are | ||||||
| mutually exclusive. | mutually exclusive. | ||||||
| @@ -1128,6 +1185,9 @@ If this option is used several times, each occurrence will toggle it on/off. | |||||||
| Specify user and password to use for server authentication. Overrides | Specify user and password to use for server authentication. Overrides | ||||||
| \fI-n/--netrc\fP and \fI--netrc-optional\fP. | \fI-n/--netrc\fP and \fI--netrc-optional\fP. | ||||||
|  |  | ||||||
|  | If you just give the user name (without entering a colon) curl will prompt for | ||||||
|  | a password. | ||||||
|  |  | ||||||
| If you use an SSPI-enabled curl binary and do NTLM authentication, you can | If you use an SSPI-enabled curl binary and do NTLM authentication, you can | ||||||
| force curl to pick up the user name and password from your environment by | force curl to pick up 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 :". | ||||||
|   | |||||||
| @@ -18,6 +18,9 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <curl/multi.h> | #include <curl/multi.h> | ||||||
|  | #ifdef WIN32 | ||||||
|  | #include <windows.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static const char *urls[] = { | static const char *urls[] = { | ||||||
|   "http://www.microsoft.com", |   "http://www.microsoft.com", | ||||||
| @@ -138,7 +141,11 @@ int main(void) | |||||||
|         L = 100; |         L = 100; | ||||||
|  |  | ||||||
|       if (M == -1) { |       if (M == -1) { | ||||||
|  | #ifdef WIN32 | ||||||
|  |         Sleep(L); | ||||||
|  | #else | ||||||
|         sleep(L / 1000); |         sleep(L / 1000); | ||||||
|  | #endif | ||||||
|       } else { |       } else { | ||||||
|         T.tv_sec = L/1000; |         T.tv_sec = L/1000; | ||||||
|         T.tv_usec = (L%1000)*1000; |         T.tv_usec = (L%1000)*1000; | ||||||
|   | |||||||
| @@ -9,7 +9,13 @@ EXTRA_DIST = README Makefile.example makefile.dj $(COMPLICATED_EXAMPLES) | |||||||
| INCLUDES = -I$(top_srcdir)/include | INCLUDES = -I$(top_srcdir)/include | ||||||
|  |  | ||||||
| LIBDIR = $(top_builddir)/lib | LIBDIR = $(top_builddir)/lib | ||||||
| CPPFLAGS = -DCURL_NO_OLDIES |  | ||||||
|  | if STATICLIB | ||||||
|  | # we need this define when building with a static lib on Windows | ||||||
|  | STATICCPPFLAGS = -DCURL_STATICLIB | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | CPPFLAGS = -DCURL_NO_OLDIES $(STATICCPPFLAGS) | ||||||
|  |  | ||||||
| # Dependencies | # Dependencies | ||||||
| LDADD = $(LIBDIR)/libcurl.la | LDADD = $(LIBDIR)/libcurl.la | ||||||
|   | |||||||
| @@ -98,5 +98,8 @@ int main(int argc, char **argv) | |||||||
|   if(chunk.memory) |   if(chunk.memory) | ||||||
|     free(chunk.memory); |     free(chunk.memory); | ||||||
|  |  | ||||||
|  |   /* we're done with libcurl, so clean it up */ | ||||||
|  |   curl_global_cleanup(); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										217
									
								
								docs/examples/smooth-gtk-thread.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								docs/examples/smooth-gtk-thread.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _ | ||||||
|  |  *  Project                     ___| | | |  _ \| | | ||||||
|  |  *                             / __| | | | |_) | | | ||||||
|  |  *                            | (__| |_| |  _ <| |___ | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * This is a multi threaded application that uses a progress bar to show | ||||||
|  |  * status.  It uses Gtk+ to make a smooth pulse. | ||||||
|  |  * | ||||||
|  |  * Written by Jud Bishop after studying the other examples provided with | ||||||
|  |  * libcurl. | ||||||
|  |  * | ||||||
|  |  * To compile (on a single line): | ||||||
|  |  * gcc -ggdb `pkg-config --cflags  --libs gtk+-2.0` -lcurl -lssl -lcrypto | ||||||
|  |  *   -lgthread-2.0 -dl  smooth-gtk-thread.c -o smooth-gtk-thread | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <gtk/gtk.h> | ||||||
|  | #include <glib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <pthread.h> | ||||||
|  |  | ||||||
|  | #include <curl/curl.h> | ||||||
|  | #include <curl/types.h> /* new for v7 */ | ||||||
|  | #include <curl/easy.h> /* new for v7 */ | ||||||
|  |  | ||||||
|  | #define NUMT 4 | ||||||
|  |  | ||||||
|  | pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; | ||||||
|  | int j = 0; | ||||||
|  | gint num_urls = 9; /* Just make sure this is less than urls[]*/ | ||||||
|  | char *urls[]= { | ||||||
|  |   "90022", | ||||||
|  |   "90023", | ||||||
|  |   "90024", | ||||||
|  |   "90025", | ||||||
|  |   "90026", | ||||||
|  |   "90027", | ||||||
|  |   "90028", | ||||||
|  |   "90029", | ||||||
|  |   "90030" | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | size_t write_file(void *ptr, size_t size, size_t nmemb, FILE *stream) | ||||||
|  | { | ||||||
|  |   /* printf("write_file\n"); */ | ||||||
|  |   return fwrite(ptr, size, nmemb, stream); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* http://xoap.weather.com/weather/local/46214?cc=*&dayf=5&unit=i */ | ||||||
|  | void *pull_one_url(void *NaN) | ||||||
|  | { | ||||||
|  |   CURL *curl; | ||||||
|  |   CURLcode res; | ||||||
|  |   gchar *http; | ||||||
|  |   FILE *outfile; | ||||||
|  |   gint i; | ||||||
|  |  | ||||||
|  |   /* Stop threads from entering unless j is incremented */ | ||||||
|  |   pthread_mutex_lock(&lock); | ||||||
|  |   while ( j < num_urls ) | ||||||
|  |   { | ||||||
|  |     printf("j = %d\n", j); | ||||||
|  |  | ||||||
|  |     http = | ||||||
|  |       g_strdup_printf("xoap.weather.com/weather/local/%s?cc=*&dayf=5&unit=i\n", | ||||||
|  |                       urls[j]); | ||||||
|  |  | ||||||
|  |     printf( "http %s", http ); | ||||||
|  |  | ||||||
|  |     curl = curl_easy_init(); | ||||||
|  |     if(curl) | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |       outfile = fopen(urls[j], "w"); | ||||||
|  |       /* printf("fopen\n"); */ | ||||||
|  |  | ||||||
|  |       /* Set the URL and transfer type */ | ||||||
|  |       curl_easy_setopt(curl, CURLOPT_URL, http); | ||||||
|  |  | ||||||
|  |       /* Write to the file */ | ||||||
|  |       curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); | ||||||
|  |       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file); | ||||||
|  |  | ||||||
|  |       j++;  /* critical line */ | ||||||
|  |       pthread_mutex_unlock(&lock); | ||||||
|  |  | ||||||
|  |       res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|  |       fclose(outfile); | ||||||
|  |       printf("fclose\n"); | ||||||
|  |  | ||||||
|  |       curl_easy_cleanup(curl); | ||||||
|  |     } | ||||||
|  |     g_free (http); | ||||||
|  |  | ||||||
|  |     /* Adds more latency, testing the mutex.*/ | ||||||
|  |     sleep(1); | ||||||
|  |  | ||||||
|  |   } /* end while */ | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | gboolean pulse_bar(gpointer data) | ||||||
|  | { | ||||||
|  |   gdk_threads_enter(); | ||||||
|  |   gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data)); | ||||||
|  |   gdk_threads_leave(); | ||||||
|  |  | ||||||
|  |   /* Return true so the function will be called again; | ||||||
|  |    * returning false removes this timeout function. | ||||||
|  |    */ | ||||||
|  |   return TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *create_thread(void *progress_bar) | ||||||
|  | { | ||||||
|  |   pthread_t tid[NUMT]; | ||||||
|  |   int i; | ||||||
|  |   int error; | ||||||
|  |  | ||||||
|  |   /* Make sure I don't create more threads than urls. */ | ||||||
|  |   for(i=0; i < NUMT && i < num_urls ; i++) { | ||||||
|  |     error = pthread_create(&tid[i], | ||||||
|  |                            NULL, /* default attributes please */ | ||||||
|  |                            pull_one_url, | ||||||
|  |                            NULL); | ||||||
|  |     if(0 != error) | ||||||
|  |       fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error); | ||||||
|  |     else | ||||||
|  |       fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* Wait for all threads to terminate. */ | ||||||
|  |   for(i=0; i < NUMT && i < num_urls; i++) { | ||||||
|  |     error = pthread_join(tid[i], NULL); | ||||||
|  |     fprintf(stderr, "Thread %d terminated\n", i); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* This stops the pulsing if you have it turned on in the progress bar | ||||||
|  |      section */ | ||||||
|  |   g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(progress_bar), | ||||||
|  |                                                     "pulse_id"))); | ||||||
|  |  | ||||||
|  |   /* This destroys the progress bar */ | ||||||
|  |   gtk_widget_destroy(progress_bar); | ||||||
|  |  | ||||||
|  |   /* [Un]Comment this out to kill the program rather than pushing close. */ | ||||||
|  |   /* gtk_main_quit(); */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   return NULL; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static gboolean cb_delete(GtkWidget *window, gpointer data) | ||||||
|  | { | ||||||
|  |   gtk_main_quit(); | ||||||
|  |   return FALSE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |   GtkWidget *top_window, *outside_frame, *inside_frame, *progress_bar; | ||||||
|  |   GtkAdjustment *adj; | ||||||
|  |  | ||||||
|  |   /* Init thread */ | ||||||
|  |   g_thread_init(NULL); | ||||||
|  |   gdk_threads_init (); | ||||||
|  |   gdk_threads_enter (); | ||||||
|  |  | ||||||
|  |   gtk_init(&argc, &argv); | ||||||
|  |  | ||||||
|  |   /* Base window */ | ||||||
|  |   top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | ||||||
|  |  | ||||||
|  |   /* Frame */ | ||||||
|  |   outside_frame = gtk_frame_new(NULL); | ||||||
|  |   gtk_frame_set_shadow_type(GTK_FRAME(outside_frame), GTK_SHADOW_OUT); | ||||||
|  |   gtk_container_add(GTK_CONTAINER(top_window), outside_frame); | ||||||
|  |  | ||||||
|  |   /* Frame */ | ||||||
|  |   inside_frame = gtk_frame_new(NULL); | ||||||
|  |   gtk_frame_set_shadow_type(GTK_FRAME(inside_frame), GTK_SHADOW_IN); | ||||||
|  |   gtk_container_set_border_width(GTK_CONTAINER(inside_frame), 5); | ||||||
|  |   gtk_container_add(GTK_CONTAINER(outside_frame), inside_frame); | ||||||
|  |  | ||||||
|  |   /* Progress bar */ | ||||||
|  |   progress_bar = gtk_progress_bar_new(); | ||||||
|  |   gtk_progress_bar_pulse (GTK_PROGRESS_BAR (progress_bar)); | ||||||
|  |   /* Make uniform pulsing */ | ||||||
|  |   gint pulse_ref = g_timeout_add (300, pulse_bar, progress_bar); | ||||||
|  |   g_object_set_data(G_OBJECT(progress_bar), "pulse_id", | ||||||
|  |                     GINT_TO_POINTER(pulse_ref)); | ||||||
|  |   gtk_container_add(GTK_CONTAINER(inside_frame), progress_bar); | ||||||
|  |  | ||||||
|  |   gtk_widget_show_all(top_window); | ||||||
|  |   printf("gtk_widget_show_all\n"); | ||||||
|  |  | ||||||
|  |   g_signal_connect(G_OBJECT (top_window), "delete-event", | ||||||
|  |                    G_CALLBACK(cb_delete), NULL); | ||||||
|  |  | ||||||
|  |   if (!g_thread_create(&create_thread, progress_bar, FALSE, NULL) != 0) | ||||||
|  |     g_warning("can't create the thread"); | ||||||
|  |  | ||||||
|  |   gtk_main(); | ||||||
|  |   gdk_threads_leave(); | ||||||
|  |   printf("gdk_threads_leave\n"); | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -18,7 +18,8 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3	 \ | |||||||
|  curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3	 \ |  curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3	 \ | ||||||
|  libcurl-tutorial.3 curl_easy_reset.3 curl_easy_escape.3		 \ |  libcurl-tutorial.3 curl_easy_reset.3 curl_easy_escape.3		 \ | ||||||
|  curl_easy_unescape.3 curl_multi_setopt.3 curl_multi_socket.3		 \ |  curl_easy_unescape.3 curl_multi_setopt.3 curl_multi_socket.3		 \ | ||||||
|  curl_multi_timeout.3 curl_formget.3 curl_multi_assign.3 |  curl_multi_timeout.3 curl_formget.3 curl_multi_assign.3		 \ | ||||||
|  |  curl_easy_pause.3 | ||||||
|  |  | ||||||
| HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html		  \ | HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html		  \ | ||||||
|  curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html	  \ |  curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html	  \ | ||||||
| @@ -36,7 +37,7 @@ HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html		  \ | |||||||
|  curl_share_strerror.html curl_global_init_mem.html libcurl-tutorial.html \ |  curl_share_strerror.html curl_global_init_mem.html libcurl-tutorial.html \ | ||||||
|  curl_easy_reset.html curl_easy_escape.html curl_easy_unescape.html	  \ |  curl_easy_reset.html curl_easy_escape.html curl_easy_unescape.html	  \ | ||||||
|  curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html	  \ |  curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html	  \ | ||||||
|  curl_formget.html curl_multi_assign.html |  curl_formget.html curl_multi_assign.html curl_easy_pause.html | ||||||
|  |  | ||||||
| PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \ | PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \ | ||||||
|  curl_easy_perform.pdf curl_easy_setopt.pdf curl_easy_duphandle.pdf	  \ |  curl_easy_perform.pdf curl_easy_setopt.pdf curl_easy_duphandle.pdf	  \ | ||||||
| @@ -53,7 +54,7 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \ | |||||||
|  curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf	  \ |  curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf	  \ | ||||||
|  curl_easy_reset.pdf curl_easy_escape.pdf curl_easy_unescape.pdf	  \ |  curl_easy_reset.pdf curl_easy_escape.pdf curl_easy_unescape.pdf	  \ | ||||||
|  curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf	  \ |  curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf	  \ | ||||||
|  curl_formget.pdf curl_multi_assign.pdf |  curl_formget.pdf curl_multi_assign.pdf curl_easy_pause.pdf | ||||||
|  |  | ||||||
| CLEANFILES = $(HTMLPAGES) $(PDFPAGES) | CLEANFILES = $(HTMLPAGES) $(PDFPAGES) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										63
									
								
								docs/libcurl/curl_easy_pause.3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								docs/libcurl/curl_easy_pause.3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | .\" $Id$ | ||||||
|  | .\" | ||||||
|  | .TH curl_easy_pause 3 "17 Dec 2007" "libcurl 7.18.0" "libcurl Manual" | ||||||
|  | .SH NAME | ||||||
|  | curl_easy_pause - pause and unpause a connection | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .B #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | .BI "CURLcode curl_easy_pause(CURL *"handle ", int "bitmask " );" | ||||||
|  |  | ||||||
|  | .SH DESCRIPTION | ||||||
|  | Using this function, you can explicitly mark a running connection to get | ||||||
|  | paused, and you can unpause a connection that was previously paused. | ||||||
|  |  | ||||||
|  | A connection can made to pause by using this function or by letting the read | ||||||
|  | or the write callbacks return the proper magic return code | ||||||
|  | (\fICURL_READFUNC_PAUSE\fP and \fICURL_WRITEFUNC_PAUSE\fP). | ||||||
|  |  | ||||||
|  | NOTE: while it may feel tempting, take care and notice that you cannot call | ||||||
|  | this function from another thread. | ||||||
|  |  | ||||||
|  | When this function is called to unpause reading, the chance is high that you | ||||||
|  | will get your write callback called before this function returns. | ||||||
|  |  | ||||||
|  | The \fBhandle\fP argument is of course identifying the handle that operates on | ||||||
|  | the connection you want to pause or unpause. | ||||||
|  |  | ||||||
|  | The \fBbitmask\fP argument is a set of bits that sets the new state of the | ||||||
|  | connection. The following bits can be used: | ||||||
|  | .IP CURLPAUSE_RECV | ||||||
|  | Pause receiving data. There will be no data received on this conneciton until | ||||||
|  | this function is called again without this bit set. Thus, the write callback | ||||||
|  | (\fICURLOPT_WRITEFUNCTION\fP) won't be called. | ||||||
|  | .IP CURLPAUSE_SEND | ||||||
|  | Pause sending data. There will be no data sent on this connection until this | ||||||
|  | function is called again without this bit set. Thus, the read callback | ||||||
|  | (\fICURLOPT_READFUNCTION\fP) won't be called. | ||||||
|  | .IP CURLPAUSE_ALL | ||||||
|  | Convenience define that pauses both directions. | ||||||
|  | .IP CURLPAUSE_CONT | ||||||
|  | Convenience define that unpauses both directions | ||||||
|  | .SH RETURN VALUE | ||||||
|  | CURLE_OK (zero) means that the option was set properly, and a non-zero return | ||||||
|  | code means something wrong occurred after the new state was set.  See the | ||||||
|  | \fIlibcurl-errors(3)\fP man page for the full list with descriptions. | ||||||
|  | .SH AVAILABILITY | ||||||
|  | This function was added in libcurl 7.18.0. Before this version, there was no | ||||||
|  | explicit support for pausing transfers. | ||||||
|  | .SH "MEMORY USE" | ||||||
|  | When pausing a read by returning the magic return code from a write callback, | ||||||
|  | the read data is already in libcurl's internal buffers so it'll have to keep | ||||||
|  | it in an allocated buffer until the reading is again unpaused using this | ||||||
|  | function. | ||||||
|  |  | ||||||
|  | If the downloaded data is compressed and is asked to get uncompressed | ||||||
|  | automatially on download, libcurl will continue to uncompress the entire | ||||||
|  | downloaded chunk and it will cache the data uncompressed. This has the side- | ||||||
|  | effect that if you download something that is compressed a lot, it can result | ||||||
|  | in a very large data amount needing to be allocated to save the data during | ||||||
|  | the pause. This said, you should probably consider not using paused reading if | ||||||
|  | you allow libcurl to uncompress data automatically. | ||||||
|  | .SH "SEE ALSO" | ||||||
|  | .BR curl_easy_cleanup "(3), " curl_easy_reset "(3)" | ||||||
| @@ -5,7 +5,7 @@ | |||||||
| .\" *                            | (__| |_| |  _ <| |___ | .\" *                            | (__| |_| |  _ <| |___ | ||||||
| .\" *                             \___|\___/|_| \_\_____| | .\" *                             \___|\___/|_| \_\_____| | ||||||
| .\" * | .\" * | ||||||
| .\" * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | .\" * Copyright (C) 1998 - 2008, 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,7 +21,7 @@ | |||||||
| .\" * $Id$ | .\" * $Id$ | ||||||
| .\" ************************************************************************** | .\" ************************************************************************** | ||||||
| .\" | .\" | ||||||
| .TH curl_easy_setopt 3 "30 Aug 2007" "libcurl 7.17.0" "libcurl Manual" | .TH curl_easy_setopt 3 "5 Jan 2008" "libcurl 7.18.0" "libcurl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl_easy_setopt \- set options for a curl easy handle | curl_easy_setopt \- set options for a curl easy handle | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -95,6 +95,10 @@ of bytes actually taken care of. If that amount differs from the amount passed | |||||||
| to your function, it'll signal an error to the library and it will abort the | to your function, it'll signal an error to the library and it will abort the | ||||||
| transfer and return \fICURLE_WRITE_ERROR\fP. | transfer and return \fICURLE_WRITE_ERROR\fP. | ||||||
|  |  | ||||||
|  | From 7.18.0, the function can return CURL_WRITEFUNC_PAUSE which then will | ||||||
|  | cause writing to this connection to become paused. See | ||||||
|  | \fIcurl_easy_pause(3)\fP for further details. | ||||||
|  |  | ||||||
| This function may be called with zero bytes data if the transfered file is | This function may be called with zero bytes data if the transfered file is | ||||||
| empty. | empty. | ||||||
|  |  | ||||||
| @@ -142,6 +146,10 @@ The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current | |||||||
| operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error | operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error | ||||||
| code from the transfer (Added in 7.12.1) | code from the transfer (Added in 7.12.1) | ||||||
|  |  | ||||||
|  | From 7.18.0, the function can return CURL_READFUNC_PAUSE which then will cause | ||||||
|  | reading from this connection to become paused. See \fIcurl_easy_pause(3)\fP | ||||||
|  | for further details. | ||||||
|  |  | ||||||
| If you set the callback pointer to NULL, or doesn't set it at all, the default | If you set the callback pointer to NULL, or doesn't set it at all, the default | ||||||
| internal read function will be used. It is simply doing an fread() on the FILE | internal read function will be used. It is simply doing an fread() on the FILE | ||||||
| * stream set with \fICURLOPT_READDATA\fP. | * stream set with \fICURLOPT_READDATA\fP. | ||||||
| @@ -163,11 +171,32 @@ something special I/O-related needs to be done that the library can't do by | |||||||
| itself. For now, rewinding the read data stream is the only action it can | itself. For now, rewinding the read data stream is the only action it can | ||||||
| request. The rewinding of the read data stream may be necessary when doing a | request. The rewinding of the read data stream may be necessary when doing a | ||||||
| HTTP PUT or POST with a multi-pass authentication method.  (Option added in | HTTP PUT or POST with a multi-pass authentication method.  (Option added in | ||||||
| 7.12.3) | 7.12.3). | ||||||
|  |  | ||||||
|  | Use \fICURLOPT_SEEKFUNCTION\fP instead to provide seeking! | ||||||
| .IP CURLOPT_IOCTLDATA | .IP CURLOPT_IOCTLDATA | ||||||
| Pass a pointer that will be untouched by libcurl and passed as the 3rd | Pass a pointer that will be untouched by libcurl and passed as the 3rd | ||||||
| argument in the ioctl callback set with \fICURLOPT_IOCTLFUNCTION\fP.  (Option | argument in the ioctl callback set with \fICURLOPT_IOCTLFUNCTION\fP.  (Option | ||||||
| added in 7.12.3) | added in 7.12.3) | ||||||
|  | .IP CURLOPT_SEEKFUNCTION | ||||||
|  | Function pointer that should match the following prototype: \fIint | ||||||
|  | function(void *instream, curl_off_t offset, int origin);\fP This function gets | ||||||
|  | called by libcurl to seek to a certain position in the input stream and can be | ||||||
|  | used to fast forward a file in a resumed upload (instead of reading all | ||||||
|  | uploaded bytes with the normal read function/callback). It is also called to | ||||||
|  | rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication | ||||||
|  | method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET, | ||||||
|  | SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl | ||||||
|  | only passes SEEK_SET. The callback must return 0 on success as returning | ||||||
|  | non-zero will cause the upload operation to fail. | ||||||
|  |  | ||||||
|  | If you forward the input arguments directly to "fseek" or "lseek", note that | ||||||
|  | the data type for \fIoffset\fP is not the same as defined for curl_off_t on | ||||||
|  | many systems! (Option added in 7.18.0) | ||||||
|  | .IP CURLOPT_SEEKDATA | ||||||
|  | Data pointer to pass to the file read function. If you use the | ||||||
|  | \fICURLOPT_SEEKFUNCTION\fP option, this is the pointer you'll get as input. If | ||||||
|  | you don't specify a seek callback, NULL is passed. (Option added in 7.18.0) | ||||||
| .IP CURLOPT_SOCKOPTFUNCTION | .IP CURLOPT_SOCKOPTFUNCTION | ||||||
| Function pointer that should match the \fIcurl_sockopt_callback\fP prototype | Function pointer that should match the \fIcurl_sockopt_callback\fP prototype | ||||||
| found in \fI<curl/curl.h>\fP. This function gets called by libcurl after the | found in \fI<curl/curl.h>\fP. This function gets called by libcurl after the | ||||||
| @@ -430,13 +459,21 @@ Pass a long with this option to set the proxy port to connect to unless it is | |||||||
| specified in the proxy string \fICURLOPT_PROXY\fP. | specified in the proxy string \fICURLOPT_PROXY\fP. | ||||||
| .IP CURLOPT_PROXYTYPE | .IP CURLOPT_PROXYTYPE | ||||||
| Pass a long with this option to set type of the proxy. Available options for | Pass a long with this option to set type of the proxy. Available options for | ||||||
| this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2) | this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2), | ||||||
| \fICURLPROXY_SOCKS5\fP. The HTTP type is default. (Added in 7.10) | \fICURLPROXY_SOCKS5\fP, \fICURLPROXY_SOCKS4A\fP (added in 7.18.0) and | ||||||
|  | \fICURLPROXY_SOCKS5_HOSTNAME\fP (added in 7.18.0). The HTTP type is | ||||||
|  | default. (Added in 7.10) | ||||||
| .IP CURLOPT_HTTPPROXYTUNNEL | .IP CURLOPT_HTTPPROXYTUNNEL | ||||||
| Set the parameter to non-zero to get the library to tunnel all operations | Set the parameter to non-zero to get the library to tunnel all operations | ||||||
| through a given HTTP proxy. There is a big difference between using a proxy | through a given HTTP proxy. There is a big difference between using a proxy | ||||||
| and to tunnel through it. If you don't know what this means, you probably | and to tunnel through it. If you don't know what this means, you probably | ||||||
| don't want this tunneling option. | don't want this tunneling option. | ||||||
|  | .IP CURLOPT_SOCKS5_RESOLVE_LOCAL | ||||||
|  | Set the parameter to 1 to get the library to resolve the host name locally | ||||||
|  | instead of passing it to the proxy to resolve, when using a SOCKS5 proxy. | ||||||
|  |  | ||||||
|  | Note that libcurl before 7.18.0 always resolved the host name locally even | ||||||
|  | when SOCKS5 was used. (Added in 7.18.0) | ||||||
| .IP CURLOPT_INTERFACE | .IP CURLOPT_INTERFACE | ||||||
| Pass a char * as parameter. This set the interface name to use as outgoing | Pass a char * as parameter. This set the interface name to use as outgoing | ||||||
| network interface. The name can be an interface name, an IP address or a host | network interface. The name can be an interface name, an IP address or a host | ||||||
| @@ -670,7 +707,9 @@ and \fICURLOPT_READDATA\fP options but then you must make sure to not set | |||||||
| \fICURLOPT_POSTFIELDS\fP to anything but NULL. When providing data with a | \fICURLOPT_POSTFIELDS\fP to anything but NULL. When providing data with a | ||||||
| callback, you must transmit it using chunked transfer-encoding or you must set | callback, you must transmit it using chunked transfer-encoding or you must set | ||||||
| the size of the data with the \fICURLOPT_POSTFIELDSIZE\fP or | the size of the data with the \fICURLOPT_POSTFIELDSIZE\fP or | ||||||
| \fICURLOPT_POSTFIELDSIZE_LARGE\fP option. | \fICURLOPT_POSTFIELDSIZE_LARGE\fP option. To enable chunked encoding, you | ||||||
|  | simply pass in the appropriate Transfer-Encoding header, see the | ||||||
|  | post-callback.c example. | ||||||
|  |  | ||||||
| You can override the default POST Content-Type: header by setting your own | You can override the default POST Content-Type: header by setting your own | ||||||
| with \fICURLOPT_HTTPHEADER\fP. | with \fICURLOPT_HTTPHEADER\fP. | ||||||
| @@ -1064,6 +1103,13 @@ or similar. | |||||||
| libcurl does not do a complete ASCII conversion when doing ASCII transfers | libcurl does not do a complete ASCII conversion when doing ASCII transfers | ||||||
| over FTP. This is a known limitation/flaw that nobody has rectified. libcurl | over FTP. This is a known limitation/flaw that nobody has rectified. libcurl | ||||||
| simply sets the mode to ascii and performs a standard transfer. | simply sets the mode to ascii and performs a standard transfer. | ||||||
|  | .IP CURLOPT_PROXY_TRANSFER_MODE | ||||||
|  | Pass a long. If the value is set to 1 (one), it tells libcurl to set the | ||||||
|  | transfer mode (binary or ASCII) for FTP transfers done via an HTTP proxy, by | ||||||
|  | appending ;type=a or ;type=i to the URL. Without this setting, or it being | ||||||
|  | set to 0 (zero, the default), \fICURLOPT_TRANSFERTEXT\fP has no effect when | ||||||
|  | doing FTP via a proxy. Beware that not all proxies support this feature. | ||||||
|  | (Added in 7.18.0) | ||||||
| .IP CURLOPT_CRLF | .IP CURLOPT_CRLF | ||||||
| Convert Unix newlines to CRLF newlines on transfers. | Convert Unix newlines to CRLF newlines on transfers. | ||||||
| .IP CURLOPT_RANGE | .IP CURLOPT_RANGE | ||||||
| @@ -1073,6 +1119,8 @@ transfers also support several intervals, separated with commas as in | |||||||
| \fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP | \fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP | ||||||
| server to send the response document in pieces (using standard MIME separation | server to send the response document in pieces (using standard MIME separation | ||||||
| techniques). Pass a NULL to this option to disable the use of ranges. | techniques). Pass a NULL to this option to disable the use of ranges. | ||||||
|  |  | ||||||
|  | Ranges work on HTTP, FTP and FILE (since 7.18.0) transfers only. | ||||||
| .IP CURLOPT_RESUME_FROM | .IP CURLOPT_RESUME_FROM | ||||||
| Pass a long as parameter. It contains the offset in number of bytes that you | Pass a long as parameter. It contains the offset in number of bytes that you | ||||||
| want the transfer to start from. Set this option to 0 to make the transfer | want the transfer to start from. Set this option to 0 to make the transfer | ||||||
| @@ -1491,6 +1539,14 @@ this curl handle use the data from the shared handle instead of keeping the | |||||||
| data to itself. This enables several curl handles to share data. If the curl | data to itself. This enables several curl handles to share data. If the curl | ||||||
| handles are used simultaneously, you \fBMUST\fP use the locking methods in the | handles are used simultaneously, you \fBMUST\fP use the locking methods in the | ||||||
| share handle. See \fIcurl_share_setopt(3)\fP for details. | share handle. See \fIcurl_share_setopt(3)\fP for details. | ||||||
|  |  | ||||||
|  | If you add a share that is set to share cookies, your easy handle will use | ||||||
|  | that cookie cache and get the cookie engine enabled. If you unshare an object | ||||||
|  | that were using cookies (or change to another object that doesn't share | ||||||
|  | cookies), the easy handle will get its cookie engine disabled. | ||||||
|  |  | ||||||
|  | Data that the share object is not set to share will be dealt with the usual | ||||||
|  | way, as if no share was used. | ||||||
| .IP CURLOPT_NEW_FILE_PERMS | .IP CURLOPT_NEW_FILE_PERMS | ||||||
| Pass a long as a parameter, containing the value of the permissions that will | Pass a long as a parameter, containing the value of the permissions that will | ||||||
| be assigned to newly created files on the remote server.  The default value is | be assigned to newly created files on the remote server.  The default value is | ||||||
|   | |||||||
| @@ -47,10 +47,11 @@ changes. The timeout value is at what latest time the application should call | |||||||
| one of the \&"performing" functions of the multi interface | one of the \&"performing" functions of the multi interface | ||||||
| (\fIcurl_multi_socket(3)\fP, \fIcurl_multi_socket_all(3)\fP and | (\fIcurl_multi_socket(3)\fP, \fIcurl_multi_socket_all(3)\fP and | ||||||
| \fIcurl_multi_perform(3)\fP) - to allow libcurl to keep timeouts and retries | \fIcurl_multi_perform(3)\fP) - to allow libcurl to keep timeouts and retries | ||||||
| etc to work. Libcurl attempts to limit calling this only when the fixed future | etc to work. A timeout value of -1 means that there is no timeout at all, and | ||||||
| timeout time actually change. See also \fICURLMOPT_TIMERDATA\fP. This callback | 0 means that the timeout is already reached. Libcurl attempts to limit calling | ||||||
| can be used instead of, or in addition to, \fIcurl_multi_timeout(3)\fP. (Added | this only when the fixed future timeout time actually change. See also | ||||||
| in 7.16.0) | \fICURLMOPT_TIMERDATA\fP. This callback can be used instead of, or in addition | ||||||
|  | to, \fIcurl_multi_timeout(3)\fP. (Added in 7.16.0) | ||||||
| .IP CURLMOPT_TIMERDATA | .IP CURLMOPT_TIMERDATA | ||||||
| Pass a pointer to whatever you want passed to the | Pass a pointer to whatever you want passed to the | ||||||
| \fBcurl_multi_timer_callback\fP's third argument, the userp pointer.  This is | \fBcurl_multi_timer_callback\fP's third argument, the userp pointer.  This is | ||||||
|   | |||||||
| @@ -23,6 +23,10 @@ The timeout value returned in the long \fBtimeout\fP points to, is in number | |||||||
| of milliseconds at this very moment. If 0, it means you should proceed | of milliseconds at this very moment. If 0, it means you should proceed | ||||||
| immediately without waiting for anything. If it returns -1, there's no timeout | immediately without waiting for anything. If it returns -1, there's no timeout | ||||||
| at all set. | at all set. | ||||||
|  |  | ||||||
|  | Note: if libcurl returns a -1 timeout here, it just means that libcurl | ||||||
|  | currently has no stored timeout value. You must not wait too long (more than a | ||||||
|  | few seconds perhaps) before you call curl_multi_perform() again. | ||||||
| .SH "RETURN VALUE" | .SH "RETURN VALUE" | ||||||
| The standard CURLMcode for multi interface error codes. | The standard CURLMcode for multi interface error codes. | ||||||
| .SH "TYPICAL USAGE" | .SH "TYPICAL USAGE" | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -29,6 +29,14 @@ | |||||||
|  |  | ||||||
| #include "curlver.h" /* the libcurl version defines */ | #include "curlver.h" /* the libcurl version defines */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Define WIN32 when build target is Win32 API | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) | ||||||
|  | #define WIN32 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
|  |  | ||||||
| @@ -41,12 +49,42 @@ | |||||||
| # include <time.h> | # include <time.h> | ||||||
| #endif /* defined (vms) */ | #endif /* defined (vms) */ | ||||||
|  |  | ||||||
| typedef void CURL; | #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \ | ||||||
|  |   !defined(__CYGWIN__) || defined(__MINGW32__) | ||||||
|  | #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H)) | ||||||
|  | /* The check above prevents the winsock2 inclusion if winsock.h already was | ||||||
|  |    included, since they can't co-exist without problems */ | ||||||
|  | #include <winsock2.h> | ||||||
|  | #include <ws2tcpip.h> | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | /* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish | ||||||
|  |    libc5-based Linux systems. Only include it on system that are known to | ||||||
|  |    require it! */ | ||||||
|  | #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || defined(__minix) | ||||||
|  | #include <sys/select.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef _WIN32_WCE | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #endif | ||||||
|  | #ifndef __WATCOMC__ | ||||||
|  | #include <sys/time.h> | ||||||
|  | #endif | ||||||
|  | #include <sys/types.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef __BEOS__ | ||||||
|  | #include <support/SupportDefs.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef  __cplusplus | #ifdef  __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | typedef void CURL; | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Decorate exportable functions for Win32 DLL linking. |  * Decorate exportable functions for Win32 DLL linking. | ||||||
|  * This avoids using a .def file for building libcurl.dll. |  * This avoids using a .def file for building libcurl.dll. | ||||||
| @@ -139,38 +177,6 @@ extern "C" { | |||||||
| #undef FILESIZEBITS | #undef FILESIZEBITS | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(_WIN32) && !defined(WIN32) |  | ||||||
| /* Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we |  | ||||||
|    make this adjustment to catch this. */ |  | ||||||
| #define WIN32 1 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \ |  | ||||||
|   !defined(__CYGWIN__) || defined(__MINGW32__) |  | ||||||
| #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H)) |  | ||||||
| /* The check above prevents the winsock2 inclusion if winsock.h already was |  | ||||||
|    included, since they can't co-exist without problems */ |  | ||||||
| #include <winsock2.h> |  | ||||||
| #include <ws2tcpip.h> |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
|  |  | ||||||
| /* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish |  | ||||||
|    libc5-based Linux systems. Only include it on system that are known to |  | ||||||
|    require it! */ |  | ||||||
| #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || defined(__minix) |  | ||||||
| #include <sys/select.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef _WIN32_WCE |  | ||||||
| #include <sys/socket.h> |  | ||||||
| #endif |  | ||||||
| #ifndef __WATCOMC__ |  | ||||||
| #include <sys/time.h> |  | ||||||
| #endif |  | ||||||
| #include <sys/types.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef curl_socket_typedef | #ifndef curl_socket_typedef | ||||||
| /* socket typedef */ | /* socket typedef */ | ||||||
| #ifdef WIN32 | #ifdef WIN32 | ||||||
| @@ -224,7 +230,9 @@ typedef int (*curl_progress_callback)(void *clientp, | |||||||
|      time for those who feel adventurous. */ |      time for those who feel adventurous. */ | ||||||
| #define CURL_MAX_WRITE_SIZE 16384 | #define CURL_MAX_WRITE_SIZE 16384 | ||||||
| #endif | #endif | ||||||
|  | /* This is a magic return code for the write callback that, when returned, | ||||||
|  |    will signal libcurl to pause receving on the current transfer. */ | ||||||
|  | #define CURL_WRITEFUNC_PAUSE 0x10000001 | ||||||
| typedef size_t (*curl_write_callback)(char *buffer, | typedef size_t (*curl_write_callback)(char *buffer, | ||||||
|                                       size_t size, |                                       size_t size, | ||||||
|                                       size_t nitems, |                                       size_t nitems, | ||||||
| @@ -233,6 +241,13 @@ typedef size_t (*curl_write_callback)(char *buffer, | |||||||
| /* This is a return code for the read callback that, when returned, will | /* This is a return code for the read callback that, when returned, will | ||||||
|    signal libcurl to immediately abort the current transfer. */ |    signal libcurl to immediately abort the current transfer. */ | ||||||
| #define CURL_READFUNC_ABORT 0x10000000 | #define CURL_READFUNC_ABORT 0x10000000 | ||||||
|  | /* This is a return code for the read callback that, when returned, will | ||||||
|  |    signal libcurl to pause sending data on the current transfer. */ | ||||||
|  | #define CURL_READFUNC_PAUSE 0x10000001 | ||||||
|  | typedef int (*curl_seek_callback)(void *instream, | ||||||
|  |                                   curl_off_t offset, | ||||||
|  | 				  int origin); /* 'whence' */ | ||||||
|  |  | ||||||
| typedef size_t (*curl_read_callback)(char *buffer, | typedef size_t (*curl_read_callback)(char *buffer, | ||||||
|                                       size_t size, |                                       size_t size, | ||||||
|                                       size_t nitems, |                                       size_t nitems, | ||||||
| @@ -251,7 +266,9 @@ struct curl_sockaddr { | |||||||
|   int family; |   int family; | ||||||
|   int socktype; |   int socktype; | ||||||
|   int protocol; |   int protocol; | ||||||
|   socklen_t addrlen; |   unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it | ||||||
|  |                            turned really ugly and painful on the systems that | ||||||
|  |                            lack this type */ | ||||||
|   struct sockaddr addr; |   struct sockaddr addr; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -487,10 +504,15 @@ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */ | |||||||
|                                           void *userptr); |                                           void *userptr); | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|   CURLPROXY_HTTP = 0, |   CURLPROXY_HTTP = 0,   /* added in 7.10 */ | ||||||
|   CURLPROXY_SOCKS4 = 4, |   CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already | ||||||
|   CURLPROXY_SOCKS5 = 5 |                            in 7.10 */ | ||||||
| } curl_proxytype; |   CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ | ||||||
|  |   CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ | ||||||
|  |   CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the | ||||||
|  |                                    host name rather than the IP address. added | ||||||
|  |                                    in 7.18.0 */ | ||||||
|  | } curl_proxytype;  /* this enum was added in 7.10 */ | ||||||
|  |  | ||||||
| #define CURLAUTH_NONE         0       /* nothing */ | #define CURLAUTH_NONE         0       /* nothing */ | ||||||
| #define CURLAUTH_BASIC        (1<<0)  /* Basic (default) */ | #define CURLAUTH_BASIC        (1<<0)  /* Basic (default) */ | ||||||
| @@ -935,7 +957,7 @@ typedef enum { | |||||||
|   CINIT(SHARE, OBJECTPOINT, 100), |   CINIT(SHARE, OBJECTPOINT, 100), | ||||||
|  |  | ||||||
|   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), |   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), | ||||||
|      CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */ |      CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ | ||||||
|   CINIT(PROXYTYPE, LONG, 101), |   CINIT(PROXYTYPE, LONG, 101), | ||||||
|  |  | ||||||
|   /* Set the Accept-Encoding string. Use this to tell a server you would like |   /* Set the Accept-Encoding string. Use this to tell a server you would like | ||||||
| @@ -1159,6 +1181,13 @@ typedef enum { | |||||||
|   /* POST volatile input fields. */ |   /* POST volatile input fields. */ | ||||||
|   CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), |   CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), | ||||||
|  |  | ||||||
|  |   /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */ | ||||||
|  |   CINIT(PROXY_TRANSFER_MODE, LONG, 166), | ||||||
|  |  | ||||||
|  |   /* Callback function for seeking in the input stream */ | ||||||
|  |   CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), | ||||||
|  |   CINIT(SEEKDATA, OBJECTPOINT, 168), | ||||||
|  |  | ||||||
|   CURLOPT_LASTENTRY /* the last unused */ |   CURLOPT_LASTENTRY /* the last unused */ | ||||||
| } CURLoption; | } CURLoption; | ||||||
|  |  | ||||||
| @@ -1241,10 +1270,6 @@ typedef enum { | |||||||
|   CURL_TIMECOND_LAST |   CURL_TIMECOND_LAST | ||||||
| } curl_TimeCond; | } curl_TimeCond; | ||||||
|  |  | ||||||
| #ifdef __BEOS__ |  | ||||||
| #include <support/SupportDefs.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* curl_strequal() and curl_strnequal() are subject for removal in a future | /* curl_strequal() and curl_strnequal() are subject for removal in a future | ||||||
|    libcurl, see lib/README.curlx for details */ |    libcurl, see lib/README.curlx for details */ | ||||||
| @@ -1737,6 +1762,26 @@ CURL_EXTERN const char *curl_easy_strerror(CURLcode); | |||||||
|  */ |  */ | ||||||
| CURL_EXTERN const char *curl_share_strerror(CURLSHcode); | CURL_EXTERN const char *curl_share_strerror(CURLSHcode); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * NAME curl_easy_pause() | ||||||
|  |  * | ||||||
|  |  * DESCRIPTION | ||||||
|  |  * | ||||||
|  |  * The curl_easy_pause function pauses or unpauses transfers. Select the new | ||||||
|  |  * state by setting the bitmask, use the convenience defines below. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); | ||||||
|  |  | ||||||
|  | #define CURLPAUSE_RECV      (1<<0) | ||||||
|  | #define CURLPAUSE_RECV_CONT (0) | ||||||
|  |  | ||||||
|  | #define CURLPAUSE_SEND      (1<<2) | ||||||
|  | #define CURLPAUSE_SEND_CONT (0) | ||||||
|  |  | ||||||
|  | #define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND) | ||||||
|  | #define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) | ||||||
|  |  | ||||||
| #ifdef  __cplusplus | #ifdef  __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -26,15 +26,18 @@ | |||||||
| /* This header file contains nothing but libcurl version info, generated by | /* This header file contains nothing but libcurl version info, generated by | ||||||
|    a script at release-time. This was made its own header file in 7.11.2 */ |    a script at release-time. This was made its own header file in 7.11.2 */ | ||||||
|  |  | ||||||
|  | /* This is the global package copyright */ | ||||||
|  | #define LIBCURL_COPYRIGHT "1996 - 2008 Daniel Stenberg, <daniel@haxx.se>." | ||||||
|  |  | ||||||
| /* 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.17.1-CVS" | #define LIBCURL_VERSION "7.18.0-CVS" | ||||||
|  |  | ||||||
| /* 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 17 | #define LIBCURL_VERSION_MINOR 18 | ||||||
| #define LIBCURL_VERSION_PATCH 1 | #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 | ||||||
|    parsing and comparions by programs. The LIBCURL_VERSION_NUM define will |    parsing and comparions by programs. The LIBCURL_VERSION_NUM define will | ||||||
| @@ -51,7 +54,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 0x071101 | #define LIBCURL_VERSION_NUM 0x071200 | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * 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 | ||||||
|   | |||||||
| @@ -1,21 +1,32 @@ | |||||||
| # | # | ||||||
| #  Watcom / OpenWatcom / Win32 makefile for libcurl. | #  Watcom / OpenWatcom / Win32 makefile for libcurl. | ||||||
| #  G. Vanem <giva@bgnett.no> | #  G. Vanem <gvanem@broadpark.no> | ||||||
| # | # | ||||||
| # $Id$ | # $Id$ | ||||||
|  |  | ||||||
| TARGETS = ca-bundle.h libcurl_wc.lib libcurl_wc.dll libcurl_wc_imp.lib | TARGETS = ca-bundle.h libcurl_wc.dll libcurl_wc_imp.lib | ||||||
|  |  | ||||||
| CC = wcc386 | CC = wcc386 | ||||||
|  |  | ||||||
| CFLAGS = -3r -mf -d3 -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -bt=nt -bd & | CFLAGS = -3r -mf -d3 -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm -bt=nt & | ||||||
|          -d+ -dWIN32 -dCURL_CA_BUNDLE=getenv("CURL_CA_BUNDLE")                     & |          -bd -d+ -dWIN32 -dCURL_CA_BUNDLE=getenv("CURL_CA_BUNDLE")                 & | ||||||
|          -dBUILDING_LIBCURL -dWITHOUT_MM_LIB -dHAVE_SPNEGO=1 -dENABLE_IPV6         & |          -dBUILDING_LIBCURL -dWITHOUT_MM_LIB -dHAVE_SPNEGO=1 -dENABLE_IPV6         & | ||||||
|          -dDEBUG_THREADING_GETADDRINFO -dDEBUG=1 -dCURLDEBUG -d_WIN32_WINNT=0x0501 & |          -dDEBUG_THREADING_GETADDRINFO -dDEBUG=1 -dCURLDEBUG -d_WIN32_WINNT=0x0501 & | ||||||
|          -I. -I..\include -dCURL_DISABLE_LDAP |          -dWINBERAPI=__declspec(cdecl) -dWINLDAPAPI=__declspec(cdecl)              & | ||||||
|  |          -I. -I..\include | ||||||
|  |  | ||||||
| OBJ_DIR  = Watcom_obj | # | ||||||
| LIB_ARG  = $(OBJ_DIR)\wlib.arg | # Change to suite. | ||||||
|  | # | ||||||
|  | ZLIB_ROOT = ..\..\..\zlib-1.2.3 | ||||||
|  | USE_ZLIB  = 0 | ||||||
|  |  | ||||||
|  | !ifeq USE_ZLIB 1 | ||||||
|  | CFLAGS += -dHAVE_ZLIB_H -dHAVE_LIBZ -I$(ZLIB_ROOT) | ||||||
|  | !endif | ||||||
|  |  | ||||||
|  | OBJ_DIR  = WC_Win32.obj | ||||||
|  | C_ARG    = $(OBJ_DIR)\wcc386.arg | ||||||
| LINK_ARG = $(OBJ_DIR)\wlink.arg | LINK_ARG = $(OBJ_DIR)\wlink.arg | ||||||
|  |  | ||||||
| OBJS = $(OBJ_DIR)\base64.obj           $(OBJ_DIR)\connect.obj     & | OBJS = $(OBJ_DIR)\base64.obj           $(OBJ_DIR)\connect.obj     & | ||||||
| @@ -50,7 +61,7 @@ OBJS = $(OBJ_DIR)\base64.obj           $(OBJ_DIR)\connect.obj     & | |||||||
|  |  | ||||||
| RESOURCE = $(OBJ_DIR)\libcurl.res | RESOURCE = $(OBJ_DIR)\libcurl.res | ||||||
|  |  | ||||||
| all: $(OBJ_DIR) $(TARGETS) .SYMBOLIC | all: $(OBJ_DIR) $(C_ARG) $(TARGETS) .SYMBOLIC | ||||||
| 	@echo Welcome to libcurl | 	@echo Welcome to libcurl | ||||||
|  |  | ||||||
| $(OBJ_DIR): | $(OBJ_DIR): | ||||||
| @@ -59,17 +70,14 @@ $(OBJ_DIR): | |||||||
| ca-bundle.h: | ca-bundle.h: | ||||||
| 	@echo /* dummy ca-bundle.h. Not used */ > $@ | 	@echo /* dummy ca-bundle.h. Not used */ > $@ | ||||||
|  |  | ||||||
| libcurl_wc.lib: $(OBJS) $(LIB_ARG) | libcurl_wc.dll libcurl_wc_imp.lib: $(OBJS) $(RESOURCE) $(LINK_ARG) | ||||||
| 	wlib -q -b -c $@ @$(LIB_ARG) |  | ||||||
|  |  | ||||||
| libcurl_wc.dll: $(OBJS) $(RESOURCE) $(LINK_ARG) |  | ||||||
| 	wlink name libcurl_wc.dll @$(LINK_ARG) | 	wlink name libcurl_wc.dll @$(LINK_ARG) | ||||||
|  |  | ||||||
| clean: .SYMBOLIC | clean: .SYMBOLIC | ||||||
| 	- rm -f $(OBJS) $(RESOURCE) | 	- rm -f $(OBJS) $(RESOURCE) | ||||||
|  |  | ||||||
| vclean realclean: clean .SYMBOLIC | vclean realclean: clean .SYMBOLIC | ||||||
| 	- rm -f $(TARGETS) $(LIB_ARG) $(LINK_ARG) libcurl_wc.map | 	- rm -f $(TARGETS) $(C_ARG) $(LINK_ARG) libcurl_wc.map | ||||||
| 	- rmdir $(OBJ_DIR) | 	- rmdir $(OBJ_DIR) | ||||||
|  |  | ||||||
| .ERASE | .ERASE | ||||||
| @@ -78,12 +86,11 @@ $(RESOURCE): libcurl.rc | |||||||
|  |  | ||||||
| .ERASE | .ERASE | ||||||
| .c{$(OBJ_DIR)}.obj: | .c{$(OBJ_DIR)}.obj: | ||||||
| 	$(CC) $[@ $(CFLAGS) -fo=$@ | 	$(CC) $[@ @$(C_ARG) -fo=$@ | ||||||
| 	@echo . |  | ||||||
|  |  | ||||||
| $(LIB_ARG): $(__MAKEFILES__) | $(C_ARG): $(__MAKEFILES__) | ||||||
| 	%create $^@ | 	%create $^@ | ||||||
| 	for %f in ($(OBJS)) do @%append $^@ +- %f | 	%append $^@ $(CFLAGS) | ||||||
|  |  | ||||||
| $(LINK_ARG): $(__MAKEFILES__) | $(LINK_ARG): $(__MAKEFILES__) | ||||||
| 	%create $^@ | 	%create $^@ | ||||||
| @@ -91,7 +98,10 @@ $(LINK_ARG): $(__MAKEFILES__) | |||||||
| 	@%append $^@ file { $(OBJS) } | 	@%append $^@ file { $(OBJS) } | ||||||
| 	@%append $^@ option quiet, map, caseexact, eliminate, implib=libcurl_wc_imp.lib, | 	@%append $^@ option quiet, map, caseexact, eliminate, implib=libcurl_wc_imp.lib, | ||||||
| 	@%append $^@ res=$(RESOURCE) libpath $(%watcom)\lib386;$(%watcom)\lib386\nt | 	@%append $^@ res=$(RESOURCE) libpath $(%watcom)\lib386;$(%watcom)\lib386\nt | ||||||
| 	@%append $^@ library clib3r.lib, ws2_32.lib | 	@%append $^@ library clib3r.lib, wldap32.lib, ws2_32.lib | ||||||
|  | !ifeq USE_ZLIB 1 | ||||||
|  | 	@%append $^@ library $(ZLIB_ROOT)\zlib.lib | ||||||
|  | !endif | ||||||
|  |  | ||||||
| # | # | ||||||
| # Dependencies based on "gcc -MM .." | # Dependencies based on "gcc -MM .." | ||||||
|   | |||||||
| @@ -21,11 +21,11 @@ ZLIB_PATH = ../../zlib-1.2.3 | |||||||
| endif | endif | ||||||
| # Edit the path below to point to the base of your OpenSSL package. | # Edit the path below to point to the base of your OpenSSL package. | ||||||
| ifndef OPENSSL_PATH | ifndef OPENSSL_PATH | ||||||
| OPENSSL_PATH = ../../openssl-0.9.8e | OPENSSL_PATH = ../../openssl-0.9.8g | ||||||
| endif | endif | ||||||
| # Edit the path below to point to the base of your LibSSH2 package. | # Edit the path below to point to the base of your LibSSH2 package. | ||||||
| ifndef LIBSSH2_PATH | ifndef LIBSSH2_PATH | ||||||
| LIBSSH2_PATH = ../../libssh2-0.17 | LIBSSH2_PATH = ../../libssh2-0.18 | ||||||
| endif | endif | ||||||
| # Edit the path below to point to the base of your Novell LDAP NDK. | # Edit the path below to point to the base of your Novell LDAP NDK. | ||||||
| ifndef LDAP_SDK | ifndef LDAP_SDK | ||||||
|   | |||||||
| @@ -20,12 +20,12 @@ endif | |||||||
|  |  | ||||||
| # Edit the path below to point to the base of your OpenSSL package. | # Edit the path below to point to the base of your OpenSSL package. | ||||||
| ifndef OPENSSL_PATH | ifndef OPENSSL_PATH | ||||||
| OPENSSL_PATH = ../../openssl-0.9.8e | OPENSSL_PATH = ../../openssl-0.9.8g | ||||||
| endif | endif | ||||||
|  |  | ||||||
| # Edit the path below to point to the base of your LibSSH2 package. | # Edit the path below to point to the base of your LibSSH2 package. | ||||||
| ifndef LIBSSH2_PATH | ifndef LIBSSH2_PATH | ||||||
| LIBSSH2_PATH = ../../libssh2-0.16 | LIBSSH2_PATH = ../../libssh2-0.18 | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifndef INSTDIR | ifndef INSTDIR | ||||||
| @@ -35,7 +35,7 @@ endif | |||||||
| # Edit the vars below to change NLM target settings. | # Edit the vars below to change NLM target settings. | ||||||
| TARGET  = libcurl | TARGET  = libcurl | ||||||
| VERSION	= $(LIBCURL_VERSION) | VERSION	= $(LIBCURL_VERSION) | ||||||
| COPYR	= Copyright (C) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se> | COPYR	= Copyright (C) $(LIBCURL_COPYRIGHT_STR) | ||||||
| DESCR	= cURL libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - http://curl.haxx.se | DESCR	= cURL libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - http://curl.haxx.se | ||||||
| MTSAFE	= YES | MTSAFE	= YES | ||||||
| STACK	= 64000 | STACK	= 64000 | ||||||
| @@ -72,7 +72,7 @@ else | |||||||
| 	CC = gcc | 	CC = gcc | ||||||
| endif | endif | ||||||
| # a native win32 awk can be downloaded from here: | # a native win32 awk can be downloaded from here: | ||||||
| # http://www.gknw.net/development/prgtools/awk-20050424.zip | # http://www.gknw.net/development/prgtools/awk-20070501.zip | ||||||
| AWK	= awk | AWK	= awk | ||||||
| YACC	= bison -y | YACC	= bison -y | ||||||
| CP	= cp -afv | CP	= cp -afv | ||||||
| @@ -336,9 +336,9 @@ endif | |||||||
| ifdef IMPORTS | ifdef IMPORTS | ||||||
| 	@echo $(DL)import $(IMPORTS)$(DL) >> $@ | 	@echo $(DL)import $(IMPORTS)$(DL) >> $@ | ||||||
| endif | endif | ||||||
| ifeq ($(LD),nlmconv) | ifeq ($(findstring nlmconv,$(LD)),nlmconv) | ||||||
| 	@echo $(DL)input $(OBJL)$(DL) >> $@ |  | ||||||
| 	@echo $(DL)input $(PRELUDE)$(DL) >> $@ | 	@echo $(DL)input $(PRELUDE)$(DL) >> $@ | ||||||
|  | 	@echo $(DL)input $(OBJL)$(DL) >> $@ | ||||||
| #ifdef LDLIBS | #ifdef LDLIBS | ||||||
| #	@echo $(DL)input $(LDLIBS)$(DL) >> $@ | #	@echo $(DL)input $(LDLIBS)$(DL) >> $@ | ||||||
| #endif | #endif | ||||||
| @@ -372,7 +372,6 @@ ifeq ($(LIBARCH),CLIB) | |||||||
| 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SEND_TYPE_RETV int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_RETV int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define socklen_t int$(DL) >> $@ | 	@echo $(DL)#define socklen_t int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define DL_LDAP_FILE "ldapsdk.nlm"$(DL) >> $@ |  | ||||||
| else | else | ||||||
| 	@echo $(DL)#define OS "i586-pc-libc-NetWare"$(DL) >> $@ | 	@echo $(DL)#define OS "i586-pc-libc-NetWare"$(DL) >> $@ | ||||||
| 	@echo $(DL)#define HAVE_FTRUNCATE 1$(DL) >> $@ | 	@echo $(DL)#define HAVE_FTRUNCATE 1$(DL) >> $@ | ||||||
| @@ -405,7 +404,6 @@ else | |||||||
| 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_ARG4 int$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SEND_TYPE_RETV ssize_t$(DL) >> $@ | 	@echo $(DL)#define SEND_TYPE_RETV ssize_t$(DL) >> $@ | ||||||
| 	@echo $(DL)#define SIZEOF_STRUCT_IN6_ADDR 16$(DL) >> $@ | 	@echo $(DL)#define SIZEOF_STRUCT_IN6_ADDR 16$(DL) >> $@ | ||||||
| 	@echo $(DL)#define DL_LDAP_FILE "lldapsdk.nlm"$(DL) >> $@ |  | ||||||
| ifdef ENABLE_IPV6 | ifdef ENABLE_IPV6 | ||||||
| 	@echo $(DL)#define ENABLE_IPV6 1$(DL) >> $@ | 	@echo $(DL)#define ENABLE_IPV6 1$(DL) >> $@ | ||||||
| endif | endif | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ IMPLIB_NAME       = libcurl_imp | |||||||
| IMPLIB_NAME_DEBUG = libcurld_imp | IMPLIB_NAME_DEBUG = libcurld_imp | ||||||
|  |  | ||||||
| !IFNDEF OPENSSL_PATH | !IFNDEF OPENSSL_PATH | ||||||
| OPENSSL_PATH   = ../../openssl-0.9.8e | OPENSSL_PATH   = ../../openssl-0.9.8g | ||||||
| !ENDIF | !ENDIF | ||||||
|  |  | ||||||
| !IFNDEF ZLIB_PATH | !IFNDEF ZLIB_PATH | ||||||
|   | |||||||
| @@ -347,6 +347,26 @@ | |||||||
| #define HAVE_LONGLONG 1 | #define HAVE_LONGLONG 1 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* Define to avoid VS2005 complaining about portable C functions */ | ||||||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1400) | ||||||
|  | #define _CRT_SECURE_NO_DEPRECATE 1 | ||||||
|  | #define _CRT_NONSTDC_NO_DEPRECATE 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* VS2008 does not support Windows build targets prior to WinXP, */ | ||||||
|  | /* so, if no build target has been defined we will target WinXP. */ | ||||||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1500) | ||||||
|  | #  ifndef _WIN32_WINNT | ||||||
|  | #    define _WIN32_WINNT 0x0501 | ||||||
|  | #  endif | ||||||
|  | #  ifndef WINVER | ||||||
|  | #    define WINVER 0x0501 | ||||||
|  | #  endif | ||||||
|  | #  if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501) | ||||||
|  | #    error VS2008 does not support Windows build targets prior to WinXP | ||||||
|  | #  endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| /*                           LDAP SUPPORT                           */ | /*                           LDAP SUPPORT                           */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| @@ -370,10 +390,6 @@ | |||||||
| /*                       ADDITIONAL DEFINITIONS                     */ | /*                       ADDITIONAL DEFINITIONS                     */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| /* Defines set for VS2005 to _not_ deprecate a few functions we use. */ |  | ||||||
| #define _CRT_SECURE_NO_DEPRECATE 1 |  | ||||||
| #define _CRT_NONSTDC_NO_DEPRECATE 1 |  | ||||||
|  |  | ||||||
| /* Define cpu-machine-OS */ | /* Define cpu-machine-OS */ | ||||||
| #undef OS | #undef OS | ||||||
| #if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ | #if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ | ||||||
|   | |||||||
| @@ -308,6 +308,12 @@ | |||||||
| /* Undef keyword 'const' if it does not work.  */ | /* Undef keyword 'const' if it does not work.  */ | ||||||
| /* #undef const */ | /* #undef const */ | ||||||
|  |  | ||||||
|  | /* Define to avoid VS2005 complaining about portable C functions */ | ||||||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1400) | ||||||
|  | #define _CRT_SECURE_NO_DEPRECATE 1 | ||||||
|  | #define _CRT_NONSTDC_NO_DEPRECATE 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| /*                           LDAP SUPPORT                           */ | /*                           LDAP SUPPORT                           */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
| @@ -320,10 +326,6 @@ | |||||||
| /*                       ADDITIONAL DEFINITIONS                     */ | /*                       ADDITIONAL DEFINITIONS                     */ | ||||||
| /* ---------------------------------------------------------------- */ | /* ---------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| /* Defines set for VS2005 to _not_ deprecate a few functions we use. */ |  | ||||||
| #define _CRT_SECURE_NO_DEPRECATE 1 |  | ||||||
| #define _CRT_NONSTDC_NO_DEPRECATE 1 |  | ||||||
|  |  | ||||||
| /* Define cpu-machine-OS */ | /* Define cpu-machine-OS */ | ||||||
| #undef OS | #undef OS | ||||||
| #define OS "i386-pc-win32ce" | #define OS "i386-pc-win32ce" | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -694,7 +694,7 @@ singleipconnect(struct connectdata *conn, | |||||||
|   addr->protocol=ai->ai_protocol; |   addr->protocol=ai->ai_protocol; | ||||||
|   addr->addrlen = |   addr->addrlen = | ||||||
|     (ai->ai_addrlen < (socklen_t)sizeof(struct Curl_sockaddr_storage)) ? |     (ai->ai_addrlen < (socklen_t)sizeof(struct Curl_sockaddr_storage)) ? | ||||||
|      ai->ai_addrlen : (socklen_t)sizeof(struct Curl_sockaddr_storage); |      (unsigned int)ai->ai_addrlen : sizeof(struct Curl_sockaddr_storage); | ||||||
|   memcpy(&addr->addr, ai->ai_addr, addr->addrlen); |   memcpy(&addr->addr, ai->ai_addr, addr->addrlen); | ||||||
|  |  | ||||||
|   /* If set, use opensocket callback to get the socket */ |   /* If set, use opensocket callback to get the socket */ | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result) | |||||||
|  |  | ||||||
| static CURLcode | static CURLcode | ||||||
| inflate_stream(struct connectdata *conn, | inflate_stream(struct connectdata *conn, | ||||||
|                struct Curl_transfer_keeper *k) |                struct SingleRequest *k) | ||||||
| { | { | ||||||
|   int allow_restart = 1; |   int allow_restart = 1; | ||||||
|   z_stream *z = &k->z;          /* zlib state structure */ |   z_stream *z = &k->z;          /* zlib state structure */ | ||||||
| @@ -152,7 +152,7 @@ inflate_stream(struct connectdata *conn, | |||||||
|  |  | ||||||
| CURLcode | CURLcode | ||||||
| Curl_unencode_deflate_write(struct connectdata *conn, | Curl_unencode_deflate_write(struct connectdata *conn, | ||||||
|                             struct Curl_transfer_keeper *k, |                             struct SingleRequest *k, | ||||||
|                             ssize_t nread) |                             ssize_t nread) | ||||||
| { | { | ||||||
|   z_stream *z = &k->z;          /* zlib state structure */ |   z_stream *z = &k->z;          /* zlib state structure */ | ||||||
| @@ -265,7 +265,7 @@ static enum { | |||||||
|  |  | ||||||
| CURLcode | CURLcode | ||||||
| Curl_unencode_gzip_write(struct connectdata *conn, | Curl_unencode_gzip_write(struct connectdata *conn, | ||||||
|                          struct Curl_transfer_keeper *k, |                          struct SingleRequest *k, | ||||||
|                          ssize_t nread) |                          ssize_t nread) | ||||||
| { | { | ||||||
|   z_stream *z = &k->z;          /* zlib state structure */ |   z_stream *z = &k->z;          /* zlib state structure */ | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2007, 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 | ||||||
| @@ -32,10 +32,10 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| CURLcode Curl_unencode_deflate_write(struct connectdata *conn, | CURLcode Curl_unencode_deflate_write(struct connectdata *conn, | ||||||
|                                      struct Curl_transfer_keeper *k, |                                      struct SingleRequest *req, | ||||||
|                                      ssize_t nread); |                                      ssize_t nread); | ||||||
|  |  | ||||||
| CURLcode | CURLcode | ||||||
| Curl_unencode_gzip_write(struct connectdata *conn, | Curl_unencode_gzip_write(struct connectdata *conn, | ||||||
|                          struct Curl_transfer_keeper *k, |                          struct SingleRequest *k, | ||||||
|                          ssize_t nread); |                          ssize_t nread); | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								lib/cookie.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								lib/cookie.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -812,7 +812,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, | |||||||
| void Curl_cookie_clearall(struct CookieInfo *cookies) | void Curl_cookie_clearall(struct CookieInfo *cookies) | ||||||
| { | { | ||||||
|   if(cookies) { |   if(cookies) { | ||||||
|     Curl_cookie_freelist(cookies->cookies); |     Curl_cookie_freelist(cookies->cookies, TRUE); | ||||||
|     cookies->cookies = NULL; |     cookies->cookies = NULL; | ||||||
|     cookies->numcookies = 0; |     cookies->numcookies = 0; | ||||||
|   } |   } | ||||||
| @@ -824,16 +824,22 @@ void Curl_cookie_clearall(struct CookieInfo *cookies) | |||||||
|  * |  * | ||||||
|  * Free a list of cookies previously returned by Curl_cookie_getlist(); |  * Free a list of cookies previously returned by Curl_cookie_getlist(); | ||||||
|  * |  * | ||||||
|  |  * The 'cookiestoo' argument tells this function whether to just free the | ||||||
|  |  * list or actually also free all cookies within the list as well. | ||||||
|  |  * | ||||||
|  ****************************************************************************/ |  ****************************************************************************/ | ||||||
|  |  | ||||||
| void Curl_cookie_freelist(struct Cookie *co) | void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo) | ||||||
| { | { | ||||||
|   struct Cookie *next; |   struct Cookie *next; | ||||||
|   if(co) { |   if(co) { | ||||||
|     while(co) { |     while(co) { | ||||||
|       next = co->next; |       next = co->next; | ||||||
|       free(co); /* we only free the struct since the "members" are all |       if(cookiestoo) | ||||||
|                       just copied! */ |         freecookie(co); | ||||||
|  |       else | ||||||
|  |         free(co); /* we only free the struct since the "members" are all just | ||||||
|  |                      pointed out in the main cookie list! */ | ||||||
|       co = next; |       co = next; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -867,7 +873,7 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies) | |||||||
|       else |       else | ||||||
|         prev->next = next; |         prev->next = next; | ||||||
|  |  | ||||||
|       free(curr); |       freecookie(curr); | ||||||
|       cookies->numcookies--; |       cookies->numcookies--; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -91,7 +91,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, | |||||||
|                                     const char *, struct CookieInfo *, bool); |                                     const char *, struct CookieInfo *, bool); | ||||||
| struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, | struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, | ||||||
| 		                   const char *, bool); | 		                   const char *, bool); | ||||||
| void Curl_cookie_freelist(struct Cookie *); | void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo); | ||||||
| void Curl_cookie_clearall(struct CookieInfo *cookies); | void Curl_cookie_clearall(struct CookieInfo *cookies); | ||||||
| void Curl_cookie_clearsess(struct CookieInfo *cookies); | void Curl_cookie_clearsess(struct CookieInfo *cookies); | ||||||
| void Curl_cookie_cleanup(struct CookieInfo *); | void Curl_cookie_cleanup(struct CookieInfo *); | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								lib/dict.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								lib/dict.c
									
									
									
									
									
								
							| @@ -87,7 +87,7 @@ | |||||||
|  * Forward declarations. |  * Forward declarations. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static CURLcode Curl_dict(struct connectdata *conn, bool *done); | static CURLcode dict_do(struct connectdata *conn, bool *done); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * DICT protocol handler. |  * DICT protocol handler. | ||||||
| @@ -96,7 +96,7 @@ static CURLcode Curl_dict(struct connectdata *conn, bool *done); | |||||||
| const struct Curl_handler Curl_handler_dict = { | const struct Curl_handler Curl_handler_dict = { | ||||||
|   "DICT",                               /* scheme */ |   "DICT",                               /* scheme */ | ||||||
|   ZERO_NULL,                            /* setup_connection */ |   ZERO_NULL,                            /* setup_connection */ | ||||||
|   Curl_dict,                            /* do_it */ |   dict_do,                              /* do_it */ | ||||||
|   ZERO_NULL,                            /* done */ |   ZERO_NULL,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
|   ZERO_NULL,                            /* connect_it */ |   ZERO_NULL,                            /* connect_it */ | ||||||
| @@ -142,7 +142,7 @@ static char *unescape_word(struct SessionHandle *data, const char *inp) | |||||||
|   return dictp; |   return dictp; | ||||||
| } | } | ||||||
|  |  | ||||||
| static CURLcode Curl_dict(struct connectdata *conn, bool *done) | static CURLcode dict_do(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
|   char *word; |   char *word; | ||||||
|   char *eword; |   char *eword; | ||||||
| @@ -155,8 +155,8 @@ static CURLcode Curl_dict(struct connectdata *conn, bool *done) | |||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
|   curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; |   curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; | ||||||
|  |  | ||||||
|   char *path = data->reqdata.path; |   char *path = data->state.path; | ||||||
|   curl_off_t *bytecount = &data->reqdata.keep.bytecount; |   curl_off_t *bytecount = &data->req.bytecount; | ||||||
|  |  | ||||||
|   *done = TRUE; /* unconditionally */ |   *done = TRUE; /* unconditionally */ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										129
									
								
								lib/easy.c
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								lib/easy.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -466,14 +466,24 @@ CURLcode curl_easy_perform(CURL *curl) | |||||||
|     return CURLE_BAD_FUNCTION_ARGUMENT; |     return CURLE_BAD_FUNCTION_ARGUMENT; | ||||||
|  |  | ||||||
|   if( ! (data->share && data->share->hostcache) ) { |   if( ! (data->share && data->share->hostcache) ) { | ||||||
|  |     /* this handle is not using a shared dns cache */ | ||||||
|  |  | ||||||
|     if (Curl_global_host_cache_use(data) && |     if(data->set.global_dns_cache && | ||||||
|        (data->dns.hostcachetype != HCACHE_GLOBAL)) { |        (data->dns.hostcachetype != HCACHE_GLOBAL)) { | ||||||
|  |       /* global dns cache was requested but still isn't */ | ||||||
|  |       struct curl_hash *ptr; | ||||||
|  |  | ||||||
|       if(data->dns.hostcachetype == HCACHE_PRIVATE) |       if(data->dns.hostcachetype == HCACHE_PRIVATE) | ||||||
|  |         /* if the current cache is private, kill it first */ | ||||||
|         Curl_hash_destroy(data->dns.hostcache); |         Curl_hash_destroy(data->dns.hostcache); | ||||||
|       data->dns.hostcache = Curl_global_host_cache_get(); |  | ||||||
|  |       ptr = Curl_global_host_cache_init(); | ||||||
|  |       if(ptr) { | ||||||
|  |         /* only do this if the global cache init works */ | ||||||
|  |         data->dns.hostcache = ptr; | ||||||
|         data->dns.hostcachetype = HCACHE_GLOBAL; |         data->dns.hostcachetype = HCACHE_GLOBAL; | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if(!data->dns.hostcache) { |     if(!data->dns.hostcache) { | ||||||
|       data->dns.hostcachetype = HCACHE_PRIVATE; |       data->dns.hostcachetype = HCACHE_PRIVATE; | ||||||
| @@ -528,9 +538,9 @@ void Curl_easy_addmulti(struct SessionHandle *data, | |||||||
|  |  | ||||||
| void Curl_easy_initHandleData(struct SessionHandle *data) | void Curl_easy_initHandleData(struct SessionHandle *data) | ||||||
| { | { | ||||||
|     memset(&data->reqdata, 0, sizeof(struct HandleData)); |     memset(&data->req, 0, sizeof(struct SingleRequest)); | ||||||
|  |  | ||||||
|     data->reqdata.maxdownload = -1; |     data->req.maxdownload = -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -676,11 +686,11 @@ void curl_easy_reset(CURL *curl) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = (struct SessionHandle *)curl; |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |  | ||||||
|   Curl_safefree(data->reqdata.pathbuffer); |   Curl_safefree(data->state.pathbuffer); | ||||||
|   data->reqdata.pathbuffer=NULL; |   data->state.pathbuffer=NULL; | ||||||
|  |  | ||||||
|   Curl_safefree(data->reqdata.proto.generic); |   Curl_safefree(data->state.proto.generic); | ||||||
|   data->reqdata.proto.generic=NULL; |   data->state.proto.generic=NULL; | ||||||
|  |  | ||||||
|   /* zero out UserDefined data: */ |   /* zero out UserDefined data: */ | ||||||
|   Curl_freeset(data); |   Curl_freeset(data); | ||||||
| @@ -744,6 +754,107 @@ void curl_easy_reset(CURL *curl) | |||||||
|   data->set.new_directory_perms = 0755; /* Default permissions */ |   data->set.new_directory_perms = 0755; /* Default permissions */ | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * curl_easy_pause() allows an application to pause or unpause a specific | ||||||
|  |  * transfer and direction. This function sets the full new state for the | ||||||
|  |  * current connection this easy handle operates on. | ||||||
|  |  * | ||||||
|  |  * NOTE: if you have the receiving paused and you call this function to remove | ||||||
|  |  * the pausing, you may get your write callback called at this point. | ||||||
|  |  * | ||||||
|  |  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h | ||||||
|  |  */ | ||||||
|  | CURLcode curl_easy_pause(CURL *curl, int action) | ||||||
|  | { | ||||||
|  |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |   struct SingleRequest *k = &data->req; | ||||||
|  |   CURLcode result = CURLE_OK; | ||||||
|  |  | ||||||
|  |   /* first switch off both pause bits */ | ||||||
|  |   int newstate = k->keepon &~ (KEEP_READ_PAUSE| KEEP_WRITE_PAUSE); | ||||||
|  |  | ||||||
|  |   /* set the new desired pause bits */ | ||||||
|  |   newstate |= ((action & CURLPAUSE_RECV)?KEEP_READ_PAUSE:0) | | ||||||
|  |     ((action & CURLPAUSE_SEND)?KEEP_WRITE_PAUSE:0); | ||||||
|  |  | ||||||
|  |   /* put it back in the keepon */ | ||||||
|  |   k->keepon = newstate; | ||||||
|  |  | ||||||
|  |   if(!(newstate & KEEP_READ_PAUSE) && data->state.tempwrite) { | ||||||
|  |     /* we have a buffer for writing that we now seem to be able to deliver since | ||||||
|  |        the receive pausing is lifted! */ | ||||||
|  |  | ||||||
|  |     /* get the pointer, type and length in local copies since the function may | ||||||
|  |        return PAUSE again and then we'll get a new copy allocted and stored in | ||||||
|  |        the tempwrite variables */ | ||||||
|  |     char *tempwrite = data->state.tempwrite; | ||||||
|  |     size_t tempsize = data->state.tempwritesize; | ||||||
|  |     int temptype = data->state.tempwritetype; | ||||||
|  |     size_t chunklen; | ||||||
|  |  | ||||||
|  |     /* clear tempwrite here just to make sure it gets cleared if there's no | ||||||
|  |        further use of it, and make sure we don't clear it after the function | ||||||
|  |        invoke as it may have been set to a new value by then */ | ||||||
|  |     data->state.tempwrite = NULL; | ||||||
|  |  | ||||||
|  |     /* since the write callback API is define to never exceed | ||||||
|  |        CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact | ||||||
|  |        have more data than that in our buffer here, we must loop sending the | ||||||
|  |        data in multiple calls until there's no data left or we get another | ||||||
|  |        pause returned. | ||||||
|  |  | ||||||
|  |        A tricky part is that the function we call will "buffer" the data | ||||||
|  |        itself when it pauses on a particular buffer, so we may need to do some | ||||||
|  |        extra trickery if we get a pause return here. | ||||||
|  |     */ | ||||||
|  |     do { | ||||||
|  |       chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize; | ||||||
|  |  | ||||||
|  |       result = Curl_client_write(data->state.current_conn, | ||||||
|  |                                  temptype, tempwrite, chunklen); | ||||||
|  |       if(!result) | ||||||
|  |         /* failures abort the loop at once */ | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       if(data->state.tempwrite && (tempsize - chunklen)) { | ||||||
|  |         /* Ouch, the reading is again paused and the block we send is now | ||||||
|  |            "cached". If this is the final chunk we can leave it like this, but | ||||||
|  |            if we have more chunks that is cached after this, we need to free | ||||||
|  |            the newly cached one and put back a version that is truly the entire | ||||||
|  |            contents that is saved for later | ||||||
|  |         */ | ||||||
|  |         char *newptr; | ||||||
|  |  | ||||||
|  |         free(data->state.tempwrite); /* free the one just cached as it isn't | ||||||
|  |                                         enough */ | ||||||
|  |  | ||||||
|  |         /* note that tempsize is still the size as before the callback was | ||||||
|  |            used, and thus the whole piece of data to keep */ | ||||||
|  |         newptr = malloc(tempsize); | ||||||
|  |         if(!newptr) { | ||||||
|  |           result = CURLE_OUT_OF_MEMORY; | ||||||
|  |           /* tempwrite will be freed further down */ | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |         data->state.tempwrite = newptr; /* store new pointer */ | ||||||
|  |         memcpy(newptr, tempwrite, tempsize); | ||||||
|  |         data->state.tempwritesize = tempsize; /* store new size */ | ||||||
|  |         /* tempwrite will be freed further down */ | ||||||
|  |         break; /* go back to pausing until further notice */ | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         tempsize -= chunklen;  /* left after the call above */ | ||||||
|  |         tempwrite += chunklen; /* advance the pointer */ | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     } while((result == CURLE_OK) && tempsize); | ||||||
|  |  | ||||||
|  |     free(tempwrite); /* this is unconditionally no longer used */ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
| #ifdef CURL_DOES_CONVERSIONS | #ifdef CURL_DOES_CONVERSIONS | ||||||
| /* | /* | ||||||
|  * Curl_convert_to_network() is an internal function |  * Curl_convert_to_network() is an internal function | ||||||
|   | |||||||
							
								
								
									
										158
									
								
								lib/file.c
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								lib/file.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -70,6 +70,7 @@ | |||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #include "strtoofft.h" | ||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
| #include "progress.h" | #include "progress.h" | ||||||
| @@ -94,9 +95,10 @@ | |||||||
|  * Forward declarations. |  * Forward declarations. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static CURLcode Curl_file(struct connectdata *, bool *done); | static CURLcode file_do(struct connectdata *, bool *done); | ||||||
| static CURLcode Curl_file_done(struct connectdata *conn, | static CURLcode file_done(struct connectdata *conn, | ||||||
|                           CURLcode status, bool premature); |                           CURLcode status, bool premature); | ||||||
|  | static CURLcode file_connect(struct connectdata *conn, bool *done); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * FILE scheme handler. |  * FILE scheme handler. | ||||||
| @@ -105,10 +107,10 @@ static CURLcode Curl_file_done(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 */ |   ZERO_NULL,                            /* setup_connection */ | ||||||
|   Curl_file,                            /* do_it */ |   file_do,                              /* do_it */ | ||||||
|   Curl_file_done,                       /* done */ |   file_done,                            /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
|   ZERO_NULL,                            /* connect_it */ |   file_connect,                         /* connect_it */ | ||||||
|   ZERO_NULL,                            /* connecting */ |   ZERO_NULL,                            /* connecting */ | ||||||
|   ZERO_NULL,                            /* doing */ |   ZERO_NULL,                            /* doing */ | ||||||
|   ZERO_NULL,                            /* proto_getsock */ |   ZERO_NULL,                            /* proto_getsock */ | ||||||
| @@ -118,15 +120,70 @@ const struct Curl_handler Curl_handler_file = { | |||||||
|   PROT_FILE                             /* protocol */ |   PROT_FILE                             /* protocol */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  /* |  /* | ||||||
|  * Curl_file_connect() gets called from Curl_protocol_connect() to allow us to |   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 | ||||||
|  |   well be factored out. | ||||||
|  |  */ | ||||||
|  | static CURLcode file_range(struct connectdata *conn) | ||||||
|  | { | ||||||
|  |   curl_off_t from, to; | ||||||
|  |   curl_off_t totalsize=-1; | ||||||
|  |   char *ptr; | ||||||
|  |   char *ptr2; | ||||||
|  |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|  |   if(data->state.use_range && data->state.range) { | ||||||
|  |     from=curlx_strtoofft(data->state.range, &ptr, 0); | ||||||
|  |     while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-'))) | ||||||
|  |       ptr++; | ||||||
|  |     to=curlx_strtoofft(ptr, &ptr2, 0); | ||||||
|  |     if(ptr == ptr2) { | ||||||
|  |       /* we didn't get any digit */ | ||||||
|  |       to=-1; | ||||||
|  |     } | ||||||
|  |     if((-1 == to) && (from>=0)) { | ||||||
|  |       /* X - */ | ||||||
|  |       data->state.resume_from = from; | ||||||
|  |       DEBUGF(infof(data, "RANGE %" FORMAT_OFF_T " to end of file\n", | ||||||
|  |                    from)); | ||||||
|  |     } | ||||||
|  |     else if(from < 0) { | ||||||
|  |       /* -Y */ | ||||||
|  |       totalsize = -from; | ||||||
|  |       data->req.maxdownload = -from; | ||||||
|  |       data->state.resume_from = from; | ||||||
|  |       DEBUGF(infof(data, "RANGE the last %" FORMAT_OFF_T " bytes\n", | ||||||
|  |                    totalsize)); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       /* X-Y */ | ||||||
|  |       totalsize = to-from; | ||||||
|  |       data->req.maxdownload = totalsize+1; /* include last byte */ | ||||||
|  |       data->state.resume_from = from; | ||||||
|  |       DEBUGF(infof(data, "RANGE from %" FORMAT_OFF_T | ||||||
|  |                    " getting %" FORMAT_OFF_T " bytes\n", | ||||||
|  |                    from, data->req.maxdownload)); | ||||||
|  |     } | ||||||
|  |     DEBUGF(infof(data, "range-download from %" FORMAT_OFF_T | ||||||
|  |                  " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", | ||||||
|  |                  from, to, data->req.maxdownload)); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     data->req.maxdownload = -1; | ||||||
|  |   return CURLE_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * file_connect() gets called from Curl_protocol_connect() to allow us to | ||||||
|  * do protocol-specific actions at connect-time.  We emulate a |  * do protocol-specific actions at connect-time.  We emulate a | ||||||
|  * connect-then-transfer protocol and "connect" to the file here |  * connect-then-transfer protocol and "connect" to the file here | ||||||
|  */ |  */ | ||||||
| CURLcode Curl_file_connect(struct connectdata *conn) | static CURLcode file_connect(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *real_path = curl_easy_unescape(data, data->reqdata.path, 0, NULL); |   char *real_path = curl_easy_unescape(data, data->state.path, 0, NULL); | ||||||
|   struct FILEPROTO *file; |   struct FILEPROTO *file; | ||||||
|   int fd; |   int fd; | ||||||
| #if defined(WIN32) || defined(MSDOS) || defined(__EMX__) | #if defined(WIN32) || defined(MSDOS) || defined(__EMX__) | ||||||
| @@ -141,17 +198,17 @@ CURLcode Curl_file_connect(struct connectdata *conn) | |||||||
|      sessionhandle, deal with it */ |      sessionhandle, deal with it */ | ||||||
|   Curl_reset_reqproto(conn); |   Curl_reset_reqproto(conn); | ||||||
|  |  | ||||||
|   if (!data->reqdata.proto.file) { |   if(!data->state.proto.file) { | ||||||
|     file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1); |     file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1); | ||||||
|     if(!file) { |     if(!file) { | ||||||
|       free(real_path); |       free(real_path); | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     } |     } | ||||||
|     data->reqdata.proto.file = file; |     data->state.proto.file = file; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     /* file is not a protocol that can deal with "persistancy" */ |     /* file is not a protocol that can deal with "persistancy" */ | ||||||
|     file = data->reqdata.proto.file; |     file = data->state.proto.file; | ||||||
|     Curl_safefree(file->freepath); |     Curl_safefree(file->freepath); | ||||||
|     if(file->fd != -1) |     if(file->fd != -1) | ||||||
|       close(file->fd); |       close(file->fd); | ||||||
| @@ -199,18 +256,19 @@ CURLcode Curl_file_connect(struct connectdata *conn) | |||||||
|  |  | ||||||
|   file->fd = fd; |   file->fd = fd; | ||||||
|   if(!data->set.upload && (fd == -1)) { |   if(!data->set.upload && (fd == -1)) { | ||||||
|     failf(data, "Couldn't open file %s", data->reqdata.path); |     failf(data, "Couldn't open file %s", data->state.path); | ||||||
|     Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); |     file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); | ||||||
|     return CURLE_FILE_COULDNT_READ_FILE; |     return CURLE_FILE_COULDNT_READ_FILE; | ||||||
|   } |   } | ||||||
|  |   *done = TRUE; | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static CURLcode Curl_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->reqdata.proto.file; |   struct FILEPROTO *file = conn->data->state.proto.file; | ||||||
|   (void)status; /* not used */ |   (void)status; /* not used */ | ||||||
|   (void)premature; /* not used */ |   (void)premature; /* not used */ | ||||||
|   Curl_safefree(file->freepath); |   Curl_safefree(file->freepath); | ||||||
| @@ -218,9 +276,6 @@ static CURLcode Curl_file_done(struct connectdata *conn, | |||||||
|   if(file->fd != -1) |   if(file->fd != -1) | ||||||
|     close(file->fd); |     close(file->fd); | ||||||
|  |  | ||||||
|   free(file); |  | ||||||
|   conn->data->reqdata.proto.file= NULL; /* clear it! */ |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -232,7 +287,7 @@ static CURLcode Curl_file_done(struct connectdata *conn, | |||||||
|  |  | ||||||
| static CURLcode file_upload(struct connectdata *conn) | static CURLcode file_upload(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct FILEPROTO *file = conn->data->reqdata.proto.file; |   struct FILEPROTO *file = conn->data->state.proto.file; | ||||||
|   const char *dir = strchr(file->path, DIRSEP); |   const char *dir = strchr(file->path, DIRSEP); | ||||||
|   FILE *fp; |   FILE *fp; | ||||||
|   CURLcode res=CURLE_OK; |   CURLcode res=CURLE_OK; | ||||||
| @@ -251,7 +306,7 @@ static CURLcode file_upload(struct connectdata *conn) | |||||||
|    */ |    */ | ||||||
|   conn->fread_func = data->set.fread_func; |   conn->fread_func = data->set.fread_func; | ||||||
|   conn->fread_in = data->set.in; |   conn->fread_in = data->set.in; | ||||||
|   conn->data->reqdata.upload_fromhere = buf; |   conn->data->req.upload_fromhere = buf; | ||||||
|  |  | ||||||
|   if(!dir) |   if(!dir) | ||||||
|     return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ |     return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ | ||||||
| @@ -259,7 +314,7 @@ static CURLcode file_upload(struct connectdata *conn) | |||||||
|   if(!dir[1]) |   if(!dir[1]) | ||||||
|      return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ |      return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ | ||||||
|  |  | ||||||
|   if(data->reqdata.resume_from) |   if(data->state.resume_from) | ||||||
|     fp = fopen( file->path, "ab" ); |     fp = fopen( file->path, "ab" ); | ||||||
|   else { |   else { | ||||||
|     int fd; |     int fd; | ||||||
| @@ -288,14 +343,14 @@ static CURLcode file_upload(struct connectdata *conn) | |||||||
|     Curl_pgrsSetUploadSize(data, data->set.infilesize); |     Curl_pgrsSetUploadSize(data, data->set.infilesize); | ||||||
|  |  | ||||||
|   /* treat the negative resume offset value as the case of "-" */ |   /* treat the negative resume offset value as the case of "-" */ | ||||||
|   if(data->reqdata.resume_from < 0){ |   if(data->state.resume_from < 0) { | ||||||
|     if(stat(file->path, &file_stat)) { |     if(stat(file->path, &file_stat)) { | ||||||
|       fclose(fp); |       fclose(fp); | ||||||
|       failf(data, "Can't get the size of %s", file->path); |       failf(data, "Can't get the size of %s", file->path); | ||||||
|       return CURLE_WRITE_ERROR; |       return CURLE_WRITE_ERROR; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|       data->reqdata.resume_from = (curl_off_t)file_stat.st_size; |       data->state.resume_from = (curl_off_t)file_stat.st_size; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   while(res == CURLE_OK) { |   while(res == CURLE_OK) { | ||||||
| @@ -310,16 +365,16 @@ static CURLcode file_upload(struct connectdata *conn) | |||||||
|     nread = (size_t)readcount; |     nread = (size_t)readcount; | ||||||
|  |  | ||||||
|     /*skip bytes before resume point*/ |     /*skip bytes before resume point*/ | ||||||
|     if(data->reqdata.resume_from) { |     if(data->state.resume_from) { | ||||||
|       if( (curl_off_t)nread <= data->reqdata.resume_from ) { |       if( (curl_off_t)nread <= data->state.resume_from ) { | ||||||
|         data->reqdata.resume_from -= nread; |         data->state.resume_from -= nread; | ||||||
|         nread = 0; |         nread = 0; | ||||||
|         buf2 = buf; |         buf2 = buf; | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         buf2 = buf + data->reqdata.resume_from; |         buf2 = buf + data->state.resume_from; | ||||||
|         nread -= data->reqdata.resume_from; |         nread -= (size_t)data->state.resume_from; | ||||||
|         data->reqdata.resume_from = 0; |         data->state.resume_from = 0; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
| @@ -350,14 +405,14 @@ static CURLcode file_upload(struct connectdata *conn) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_file() is the protocol-specific function for the do-phase, separated |  * file_do() is the protocol-specific function for the do-phase, separated | ||||||
|  * from the connect-phase above. Other protocols merely setup the transfer in |  * from the connect-phase above. Other protocols merely setup the transfer in | ||||||
|  * the do-phase, to have it done in the main transfer loop but since some |  * the do-phase, to have it done in the main transfer loop but since some | ||||||
|  * platforms we support don't allow select()ing etc on file handles (as |  * platforms we support don't allow select()ing etc on file handles (as | ||||||
|  * opposed to sockets) we instead perform the whole do-operation in this |  * opposed to sockets) we instead perform the whole do-operation in this | ||||||
|  * function. |  * function. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_file(struct connectdata *conn, bool *done) | static CURLcode file_do(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
|   /* This implementation ignores the host name in conformance with |   /* This implementation ignores the host name in conformance with | ||||||
|      RFC 1738. Only local files (reachable via the standard file system) |      RFC 1738. Only local files (reachable via the standard file system) | ||||||
| @@ -371,6 +426,7 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done) | |||||||
|   curl_off_t expected_size=0; |   curl_off_t expected_size=0; | ||||||
|   bool fstated=FALSE; |   bool fstated=FALSE; | ||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
|  |   size_t bytestoread; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char *buf = data->state.buffer; |   char *buf = data->state.buffer; | ||||||
|   curl_off_t bytecount = 0; |   curl_off_t bytecount = 0; | ||||||
| @@ -379,7 +435,6 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|   *done = TRUE; /* unconditionally */ |   *done = TRUE; /* unconditionally */ | ||||||
|  |  | ||||||
|   Curl_readwrite_init(conn); |  | ||||||
|   Curl_initinfo(data); |   Curl_initinfo(data); | ||||||
|   Curl_pgrsStartNow(data); |   Curl_pgrsStartNow(data); | ||||||
|  |  | ||||||
| @@ -387,7 +442,7 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done) | |||||||
|     return file_upload(conn); |     return file_upload(conn); | ||||||
|  |  | ||||||
|   /* get the fd from the connection phase */ |   /* get the fd from the connection phase */ | ||||||
|   fd = conn->data->reqdata.proto.file->fd; |   fd = conn->data->state.proto.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)) { | ||||||
| @@ -436,13 +491,31 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done) | |||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (data->reqdata.resume_from <= expected_size) |   /* Check whether file range has been specified */ | ||||||
|     expected_size -= data->reqdata.resume_from; |   file_range(conn); | ||||||
|  |  | ||||||
|  |   /* Adjust the start offset in case we want to get the N last bytes | ||||||
|  |    * of the stream iff the filesize could be determined */ | ||||||
|  |   if(data->state.resume_from < 0) { | ||||||
|  |     if(!fstated) { | ||||||
|  |       failf(data, "Can't get the size of file."); | ||||||
|  |       return CURLE_READ_ERROR; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       data->state.resume_from += (curl_off_t)statbuf.st_size; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if(data->state.resume_from <= expected_size) | ||||||
|  |     expected_size -= data->state.resume_from; | ||||||
|   else { |   else { | ||||||
|     failf(data, "failed to resume file:// transfer"); |     failf(data, "failed to resume file:// transfer"); | ||||||
|     return CURLE_BAD_DOWNLOAD_RESUME; |     return CURLE_BAD_DOWNLOAD_RESUME; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /* A high water mark has been specified so we obey... */ | ||||||
|  |   if (data->req.maxdownload > 0) | ||||||
|  |     expected_size = data->req.maxdownload; | ||||||
|  |  | ||||||
|   if(fstated && (expected_size == 0)) |   if(fstated && (expected_size == 0)) | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|  |  | ||||||
| @@ -453,24 +526,27 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done) | |||||||
|   if(fstated) |   if(fstated) | ||||||
|     Curl_pgrsSetDownloadSize(data, expected_size); |     Curl_pgrsSetDownloadSize(data, expected_size); | ||||||
|  |  | ||||||
|   if(data->reqdata.resume_from) { |   if(data->state.resume_from) { | ||||||
|     if(data->reqdata.resume_from != |     if(data->state.resume_from != | ||||||
|        lseek(fd, data->reqdata.resume_from, SEEK_SET)) |        lseek(fd, data->state.resume_from, SEEK_SET)) | ||||||
|       return CURLE_BAD_DOWNLOAD_RESUME; |       return CURLE_BAD_DOWNLOAD_RESUME; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Curl_pgrsTime(data, TIMER_STARTTRANSFER); |   Curl_pgrsTime(data, TIMER_STARTTRANSFER); | ||||||
|  |  | ||||||
|   while(res == CURLE_OK) { |   while(res == CURLE_OK) { | ||||||
|     nread = read(fd, buf, BUFSIZE-1); |     /* Don't fill a whole buffer if we want less than all data */ | ||||||
|  |     bytestoread = (expected_size < BUFSIZE-1)?(size_t)expected_size:BUFSIZE-1; | ||||||
|  |     nread = read(fd, buf, bytestoread); | ||||||
|  |  | ||||||
|     if( nread > 0) |     if( nread > 0) | ||||||
|       buf[nread] = 0; |       buf[nread] = 0; | ||||||
|  |  | ||||||
|     if (nread <= 0) |     if (nread <= 0 || expected_size == 0) | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     bytecount += nread; |     bytecount += nread; | ||||||
|  |     expected_size -= nread; | ||||||
|  |  | ||||||
|     res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); |     res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); | ||||||
|     if(res) |     if(res) | ||||||
|   | |||||||
| @@ -25,7 +25,5 @@ | |||||||
|  ***************************************************************************/ |  ***************************************************************************/ | ||||||
| #ifndef CURL_DISABLE_FILE | #ifndef CURL_DISABLE_FILE | ||||||
| extern const struct Curl_handler Curl_handler_file; | extern const struct Curl_handler Curl_handler_file; | ||||||
|  |  | ||||||
| CURLcode Curl_file_connect(struct connectdata *); |  | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										325
									
								
								lib/ftp.c
									
									
									
									
									
								
							
							
						
						
									
										325
									
								
								lib/ftp.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -134,21 +134,21 @@ static CURLcode ftp_nb_type(struct connectdata *conn, | |||||||
|                             bool ascii, ftpstate newstate); |                             bool ascii, ftpstate newstate); | ||||||
| static int ftp_need_type(struct connectdata *conn, | static int ftp_need_type(struct connectdata *conn, | ||||||
|                          bool ascii); |                          bool ascii); | ||||||
| static CURLcode Curl_ftp(struct connectdata *conn, bool *done); | static CURLcode ftp_do(struct connectdata *conn, bool *done); | ||||||
| static CURLcode Curl_ftp_done(struct connectdata *conn, | static CURLcode ftp_done(struct connectdata *conn, | ||||||
|                               CURLcode, bool premature); |                               CURLcode, bool premature); | ||||||
| static CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done); | static CURLcode ftp_connect(struct connectdata *conn, bool *done); | ||||||
| static CURLcode Curl_ftp_disconnect(struct connectdata *conn); | static CURLcode ftp_disconnect(struct connectdata *conn); | ||||||
| static CURLcode Curl_ftp_nextconnect(struct connectdata *conn); | static CURLcode ftp_nextconnect(struct connectdata *conn); | ||||||
| static CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done); | static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); | ||||||
| static int Curl_ftp_getsock(struct connectdata *conn, | static int ftp_getsock(struct connectdata *conn, | ||||||
|                             curl_socket_t *socks, |                             curl_socket_t *socks, | ||||||
|                             int numsocks); |                             int numsocks); | ||||||
| static CURLcode Curl_ftp_doing(struct connectdata *conn, | static CURLcode ftp_doing(struct connectdata *conn, | ||||||
|                                bool *dophase_done); |                                bool *dophase_done); | ||||||
| static CURLcode Curl_ftp_setup_connection(struct connectdata * conn); | static CURLcode ftp_setup_connection(struct connectdata * conn); | ||||||
| #ifdef USE_SSL | #ifdef USE_SSL | ||||||
| static CURLcode Curl_ftps_setup_connection(struct connectdata * conn); | static CURLcode ftps_setup_connection(struct connectdata * conn); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* easy-to-use macro: */ | /* easy-to-use macro: */ | ||||||
| @@ -164,16 +164,16 @@ static CURLcode Curl_ftps_setup_connection(struct connectdata * conn); | |||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_ftp = { | const struct Curl_handler Curl_handler_ftp = { | ||||||
|   "FTP",                                /* scheme */ |   "FTP",                                /* scheme */ | ||||||
|   Curl_ftp_setup_connection,            /* setup_connection */ |   ftp_setup_connection,            /* setup_connection */ | ||||||
|   Curl_ftp,                             /* do_it */ |   ftp_do,                          /* do_it */ | ||||||
|   Curl_ftp_done,                        /* done */ |   ftp_done,                        /* done */ | ||||||
|   Curl_ftp_nextconnect,                 /* do_more */ |   ftp_nextconnect,                 /* do_more */ | ||||||
|   Curl_ftp_connect,                     /* connect_it */ |   ftp_connect,                     /* connect_it */ | ||||||
|   Curl_ftp_multi_statemach,             /* connecting */ |   ftp_multi_statemach,             /* connecting */ | ||||||
|   Curl_ftp_doing,                       /* doing */ |   ftp_doing,                       /* doing */ | ||||||
|   Curl_ftp_getsock,                     /* proto_getsock */ |   ftp_getsock,                     /* proto_getsock */ | ||||||
|   Curl_ftp_getsock,                     /* doing_getsock */ |   ftp_getsock,                     /* doing_getsock */ | ||||||
|   Curl_ftp_disconnect,                  /* disconnect */ |   ftp_disconnect,                  /* disconnect */ | ||||||
|   PORT_FTP,                             /* defport */ |   PORT_FTP,                             /* defport */ | ||||||
|   PROT_FTP                              /* protocol */ |   PROT_FTP                              /* protocol */ | ||||||
| }; | }; | ||||||
| @@ -186,16 +186,16 @@ const struct Curl_handler Curl_handler_ftp = { | |||||||
|  |  | ||||||
| const struct Curl_handler Curl_handler_ftps = { | const struct Curl_handler Curl_handler_ftps = { | ||||||
|   "FTPS",                               /* scheme */ |   "FTPS",                               /* scheme */ | ||||||
|   Curl_ftps_setup_connection,           /* setup_connection */ |   ftps_setup_connection,           /* setup_connection */ | ||||||
|   Curl_ftp,                             /* do_it */ |   ftp_do,                          /* do_it */ | ||||||
|   Curl_ftp_done,                        /* done */ |   ftp_done,                        /* done */ | ||||||
|   Curl_ftp_nextconnect,                 /* do_more */ |   ftp_nextconnect,                 /* do_more */ | ||||||
|   Curl_ftp_connect,                     /* connect_it */ |   ftp_connect,                     /* connect_it */ | ||||||
|   Curl_ftp_multi_statemach,             /* connecting */ |   ftp_multi_statemach,             /* connecting */ | ||||||
|   Curl_ftp_doing,                       /* doing */ |   ftp_doing,                       /* doing */ | ||||||
|   Curl_ftp_getsock,                     /* proto_getsock */ |   ftp_getsock,                     /* proto_getsock */ | ||||||
|   Curl_ftp_getsock,                     /* doing_getsock */ |   ftp_getsock,                     /* doing_getsock */ | ||||||
|   Curl_ftp_disconnect,                  /* disconnect */ |   ftp_disconnect,                  /* disconnect */ | ||||||
|   PORT_FTPS,                            /* defport */ |   PORT_FTPS,                            /* defport */ | ||||||
|   PROT_FTP | PROT_FTPS | PROT_SSL       /* protocol */ |   PROT_FTP | PROT_FTPS | PROT_SSL       /* protocol */ | ||||||
| }; | }; | ||||||
| @@ -403,7 +403,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, | |||||||
|                              int *ftpcode, /* return the ftp-code if done */ |                              int *ftpcode, /* return the ftp-code if done */ | ||||||
|                              size_t *size) /* size of the response */ |                              size_t *size) /* size of the response */ | ||||||
| { | { | ||||||
|   int perline; /* count bytes per line */ |   ssize_t perline; /* count bytes per line */ | ||||||
|   bool keepon=TRUE; |   bool keepon=TRUE; | ||||||
|   ssize_t gotbytes; |   ssize_t gotbytes; | ||||||
|   char *ptr; |   char *ptr; | ||||||
| @@ -418,8 +418,9 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, | |||||||
|  |  | ||||||
|   ptr=buf + ftpc->nread_resp; |   ptr=buf + ftpc->nread_resp; | ||||||
|  |  | ||||||
|   perline= (int)(ptr-ftpc->linestart_resp); /* number of bytes in the current |   /* number of bytes in the current line, so far */ | ||||||
|                                               line, so far */ |   perline = (ssize_t)(ptr-ftpc->linestart_resp); | ||||||
|  |  | ||||||
|   keepon=TRUE; |   keepon=TRUE; | ||||||
|  |  | ||||||
|   while((ftpc->nread_resp<BUFSIZE) && (keepon && !result)) { |   while((ftpc->nread_resp<BUFSIZE) && (keepon && !result)) { | ||||||
| @@ -479,10 +480,10 @@ static CURLcode ftp_readresp(curl_socket_t sockfd, | |||||||
|        * byte to a set of lines and possible just a piece of the last |        * byte to a set of lines and possible just a piece of the last | ||||||
|        * line */ |        * line */ | ||||||
|       ssize_t i; |       ssize_t i; | ||||||
|       int clipamount = 0; |       ssize_t clipamount = 0; | ||||||
|       bool restart = FALSE; |       bool restart = FALSE; | ||||||
|  |  | ||||||
|       data->reqdata.keep.headerbytecount += gotbytes; |       data->req.headerbytecount += gotbytes; | ||||||
|  |  | ||||||
|       ftpc->nread_resp += gotbytes; |       ftpc->nread_resp += gotbytes; | ||||||
|       for(i = 0; i < gotbytes; ptr++, i++) { |       for(i = 0; i < gotbytes; ptr++, i++) { | ||||||
| @@ -788,7 +789,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->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   /* send USER */ |   /* send USER */ | ||||||
|   NBFTPSENDF(conn, "USER %s", ftp->user?ftp->user:""); |   NBFTPSENDF(conn, "USER %s", ftp->user?ftp->user:""); | ||||||
|  |  | ||||||
| @@ -810,7 +811,7 @@ static CURLcode ftp_state_pwd(struct connectdata *conn) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* For the FTP "protocol connect" and "doing" phases only */ | /* For the FTP "protocol connect" and "doing" phases only */ | ||||||
| static int Curl_ftp_getsock(struct connectdata *conn, | static int ftp_getsock(struct connectdata *conn, | ||||||
|                             curl_socket_t *socks, |                             curl_socket_t *socks, | ||||||
|                             int numsocks) |                             int numsocks) | ||||||
| { | { | ||||||
| @@ -933,7 +934,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, | |||||||
|     rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, |     rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, | ||||||
|                      0, NIFLAGS); |                      0, NIFLAGS); | ||||||
|     if(rc) { |     if(rc) { | ||||||
|       failf(data, "getnameinfo() returned %d \n", rc); |       failf(data, "getnameinfo() returned %d", rc); | ||||||
|       return CURLE_FTP_PORT_FAILED; |       return CURLE_FTP_PORT_FAILED; | ||||||
|     } |     } | ||||||
|     host = hbuf; /* use this host name */ |     host = hbuf; /* use this host name */ | ||||||
| @@ -1313,7 +1314,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn) | |||||||
| static CURLcode ftp_state_post_rest(struct connectdata *conn) | static CURLcode ftp_state_post_rest(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct FTP *ftp = conn->data->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|   if(ftp->transfer != FTPTRANSFER_BODY) { |   if(ftp->transfer != FTPTRANSFER_BODY) { | ||||||
| @@ -1337,7 +1338,7 @@ static CURLcode ftp_state_post_rest(struct connectdata *conn) | |||||||
| static CURLcode ftp_state_post_size(struct connectdata *conn) | static CURLcode ftp_state_post_size(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct FTP *ftp = conn->data->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   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) { | ||||||
| @@ -1358,7 +1359,7 @@ static CURLcode ftp_state_post_size(struct connectdata *conn) | |||||||
| static CURLcode ftp_state_post_type(struct connectdata *conn) | static CURLcode ftp_state_post_type(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct FTP *ftp = conn->data->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   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) { | ||||||
| @@ -1398,11 +1399,11 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn) | |||||||
|  |  | ||||||
|   lstArg = NULL; |   lstArg = NULL; | ||||||
|   if((data->set.ftp_filemethod == FTPFILE_NOCWD) && |   if((data->set.ftp_filemethod == FTPFILE_NOCWD) && | ||||||
|      data->reqdata.path && |      data->state.path && | ||||||
|      data->reqdata.path[0] && |      data->state.path[0] && | ||||||
|      strchr(data->reqdata.path,'/')) { |      strchr(data->state.path,'/')) { | ||||||
|  |  | ||||||
|     lstArg = strdup(data->reqdata.path); |     lstArg = strdup(data->state.path); | ||||||
|     if(!lstArg) |     if(!lstArg) | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
| @@ -1465,7 +1466,7 @@ static CURLcode ftp_state_post_stortype(struct connectdata *conn) | |||||||
| static CURLcode ftp_state_post_mdtm(struct connectdata *conn) | static CURLcode ftp_state_post_mdtm(struct connectdata *conn) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct FTP *ftp = conn->data->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
| @@ -1522,13 +1523,12 @@ 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->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   curl_off_t passed=0; |  | ||||||
|  |  | ||||||
|   if((data->reqdata.resume_from && !sizechecked) || |   if((data->state.resume_from && !sizechecked) || | ||||||
|      ((data->reqdata.resume_from > 0) && sizechecked)) { |      ((data->state.resume_from > 0) && sizechecked)) { | ||||||
|     /* we're about to continue the uploading of a file */ |     /* we're about to continue the uploading of a file */ | ||||||
|     /* 1. get already existing file's size. We use the SIZE command for this |     /* 1. get already existing file's size. We use the SIZE command for this | ||||||
|        which may not exist in the server!  The SIZE command is not in |        which may not exist in the server!  The SIZE command is not in | ||||||
| @@ -1542,7 +1542,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, | |||||||
|     /* 4. lower the infilesize counter */ |     /* 4. lower the infilesize counter */ | ||||||
|     /* => transfer as usual */ |     /* => transfer as usual */ | ||||||
|  |  | ||||||
|     if(data->reqdata.resume_from < 0 ) { |     if(data->state.resume_from < 0 ) { | ||||||
|       /* Got no given size to start from, figure it out */ |       /* Got no given size to start from, figure it out */ | ||||||
|       NBFTPSENDF(conn, "SIZE %s", ftpc->file); |       NBFTPSENDF(conn, "SIZE %s", ftpc->file); | ||||||
|       state(conn, FTP_STOR_SIZE); |       state(conn, FTP_STOR_SIZE); | ||||||
| @@ -1552,14 +1552,21 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, | |||||||
|     /* enable append */ |     /* enable append */ | ||||||
|     data->set.ftp_append = TRUE; |     data->set.ftp_append = TRUE; | ||||||
|  |  | ||||||
|     /* Let's read off the proper amount of bytes from the input. If we knew it |     /* Let's read off the proper amount of bytes from the input. */ | ||||||
|        was a proper file we could've just fseek()ed but we only have a stream |     if(conn->seek_func) { | ||||||
|        here */ |       curl_off_t readthisamountnow = data->state.resume_from; | ||||||
|  |  | ||||||
|     /* TODO: allow the ioctlfunction to provide a fast forward function that |       if(conn->seek_func(conn->seek_client, | ||||||
|        can be used here and use this method only as a fallback! */ | 			 readthisamountnow, SEEK_SET) != 0) { | ||||||
|  |         failf(data, "Could not seek stream"); | ||||||
|  |         return CURLE_FTP_COULDNT_USE_REST; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     else { | ||||||
|  |       curl_off_t passed=0; | ||||||
|       do { |       do { | ||||||
|       curl_off_t readthisamountnow = (data->reqdata.resume_from - passed); |         curl_off_t readthisamountnow = (data->state.resume_from - passed); | ||||||
|         curl_off_t actuallyread; |         curl_off_t actuallyread; | ||||||
|  |  | ||||||
|         if(readthisamountnow > BUFSIZE) |         if(readthisamountnow > BUFSIZE) | ||||||
| @@ -1570,16 +1577,18 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, | |||||||
|                       conn->fread_in); |                       conn->fread_in); | ||||||
|  |  | ||||||
|         passed += actuallyread; |         passed += actuallyread; | ||||||
|       if(actuallyread != readthisamountnow) { |         if((actuallyread <= 0) || (actuallyread > readthisamountnow)) { | ||||||
|         failf(data, "Could only read %" FORMAT_OFF_T |           /* this checks for greater-than only to make sure that the | ||||||
|               " bytes from the input", passed); |              CURL_READFUNC_ABORT return code still aborts */ | ||||||
|  |           failf(data, "Failed to read data"); | ||||||
|           return CURLE_FTP_COULDNT_USE_REST; |           return CURLE_FTP_COULDNT_USE_REST; | ||||||
|         } |         } | ||||||
|     } while(passed != data->reqdata.resume_from); |       } while(passed < data->state.resume_from); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* now, decrease the size of the read */ |     /* now, decrease the size of the read */ | ||||||
|     if(data->set.infilesize>0) { |     if(data->set.infilesize>0) { | ||||||
|       data->set.infilesize -= data->reqdata.resume_from; |       data->set.infilesize -= data->state.resume_from; | ||||||
|  |  | ||||||
|       if(data->set.infilesize <= 0) { |       if(data->set.infilesize <= 0) { | ||||||
|         infof(data, "File already completely uploaded\n"); |         infof(data, "File already completely uploaded\n"); | ||||||
| @@ -1588,7 +1597,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, | |||||||
|         result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); |         result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); | ||||||
|  |  | ||||||
|         /* Set ->transfer so that we won't get any error in |         /* Set ->transfer so that we won't get any error in | ||||||
|          * Curl_ftp_done() because we didn't transfer anything! */ |          * ftp_done() because we didn't transfer anything! */ | ||||||
|         ftp->transfer = FTPTRANSFER_NONE; |         ftp->transfer = FTPTRANSFER_NONE; | ||||||
|  |  | ||||||
|         state(conn, FTP_STOP); |         state(conn, FTP_STOP); | ||||||
| @@ -1612,7 +1621,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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   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; | ||||||
| @@ -1726,7 +1735,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, | |||||||
|  |  | ||||||
|           if(conn->bits.tunnel_proxy || |           if(conn->bits.tunnel_proxy || | ||||||
|              data->set.proxytype == CURLPROXY_SOCKS5 || |              data->set.proxytype == CURLPROXY_SOCKS5 || | ||||||
|               data->set.proxytype == CURLPROXY_SOCKS4) |              data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME || | ||||||
|  |              data->set.proxytype == CURLPROXY_SOCKS4 || | ||||||
|  |              data->set.proxytype == CURLPROXY_SOCKS4A) | ||||||
|             /* proxy tunnel -> use other host info because ip_addr_str is the |             /* proxy tunnel -> use other host info because ip_addr_str is the | ||||||
|                proxy address not the ftp host */ |                proxy address not the ftp host */ | ||||||
|             snprintf(newhost, sizeof(newhost), "%s", conn->host.name); |             snprintf(newhost, sizeof(newhost), "%s", conn->host.name); | ||||||
| @@ -1780,7 +1791,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, | |||||||
|             conn->ip_addr_str); |             conn->ip_addr_str); | ||||||
|       if(conn->bits.tunnel_proxy || |       if(conn->bits.tunnel_proxy || | ||||||
|           data->set.proxytype == CURLPROXY_SOCKS5 || |           data->set.proxytype == CURLPROXY_SOCKS5 || | ||||||
|           data->set.proxytype == CURLPROXY_SOCKS4) |           data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME || | ||||||
|  |           data->set.proxytype == CURLPROXY_SOCKS4 || | ||||||
|  |           data->set.proxytype == CURLPROXY_SOCKS4A) | ||||||
|         /* proxy tunnel -> use other host info because ip_addr_str is the |         /* proxy tunnel -> use other host info because ip_addr_str is the | ||||||
|            proxy address not the ftp host */ |            proxy address not the ftp host */ | ||||||
|         snprintf(newhost, sizeof(newhost), "%s", conn->host.name); |         snprintf(newhost, sizeof(newhost), "%s", conn->host.name); | ||||||
| @@ -1877,6 +1890,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, | |||||||
|  |  | ||||||
|   switch(data->set.proxytype) { |   switch(data->set.proxytype) { | ||||||
|   case CURLPROXY_SOCKS5: |   case CURLPROXY_SOCKS5: | ||||||
|  |   case CURLPROXY_SOCKS5_HOSTNAME: | ||||||
|     result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport, |     result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport, | ||||||
|                          SECONDARYSOCKET, conn); |                          SECONDARYSOCKET, conn); | ||||||
|     break; |     break; | ||||||
| @@ -1885,7 +1899,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, | |||||||
|     break; |     break; | ||||||
|   case CURLPROXY_SOCKS4: |   case CURLPROXY_SOCKS4: | ||||||
|     result = Curl_SOCKS4(conn->proxyuser, newhost, newport, |     result = Curl_SOCKS4(conn->proxyuser, newhost, newport, | ||||||
|                          SECONDARYSOCKET, conn); |                          SECONDARYSOCKET, conn, FALSE); | ||||||
|  |     break; | ||||||
|  |   case CURLPROXY_SOCKS4A: | ||||||
|  |     result = Curl_SOCKS4(conn->proxyuser, newhost, newport, | ||||||
|  |                          SECONDARYSOCKET, conn, TRUE); | ||||||
|     break; |     break; | ||||||
|   default: |   default: | ||||||
|     failf(data, "unknown proxytype option given"); |     failf(data, "unknown proxytype option given"); | ||||||
| @@ -1907,13 +1925,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->reqdata.proto.ftp; |     struct FTP *ftp_save = data->state.proto.ftp; | ||||||
|     memset(&http_proxy, 0, sizeof(http_proxy)); |     memset(&http_proxy, 0, sizeof(http_proxy)); | ||||||
|     data->reqdata.proto.http = &http_proxy; |     data->state.proto.http = &http_proxy; | ||||||
|  |  | ||||||
|     result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); |     result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); | ||||||
|  |  | ||||||
|     data->reqdata.proto.ftp = ftp_save; |     data->state.proto.ftp = ftp_save; | ||||||
|  |  | ||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
| @@ -1963,7 +1981,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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   switch(ftpcode) { |   switch(ftpcode) { | ||||||
| @@ -2095,7 +2113,7 @@ static CURLcode ftp_state_post_retr_size(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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   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)) { | ||||||
| @@ -2104,7 +2122,7 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn, | |||||||
|   } |   } | ||||||
|   ftp->downloadsize = filesize; |   ftp->downloadsize = filesize; | ||||||
|  |  | ||||||
|   if(data->reqdata.resume_from) { |   if(data->state.resume_from) { | ||||||
|     /* We always (attempt to) get the size of downloads, so it is done before |     /* We always (attempt to) get the size of downloads, so it is done before | ||||||
|        this even when not doing resumes. */ |        this even when not doing resumes. */ | ||||||
|     if(filesize == -1) { |     if(filesize == -1) { | ||||||
| @@ -2117,28 +2135,28 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn, | |||||||
|     else { |     else { | ||||||
|       /* We got a file size report, so we check that there actually is a |       /* We got a file size report, so we check that there actually is a | ||||||
|          part of the file left to get, or else we go home.  */ |          part of the file left to get, or else we go home.  */ | ||||||
|       if(data->reqdata.resume_from< 0) { |       if(data->state.resume_from< 0) { | ||||||
|         /* We're supposed to download the last abs(from) bytes */ |         /* We're supposed to download the last abs(from) bytes */ | ||||||
|         if(filesize < -data->reqdata.resume_from) { |         if(filesize < -data->state.resume_from) { | ||||||
|           failf(data, "Offset (%" FORMAT_OFF_T |           failf(data, "Offset (%" FORMAT_OFF_T | ||||||
|                 ") was beyond file size (%" FORMAT_OFF_T ")", |                 ") was beyond file size (%" FORMAT_OFF_T ")", | ||||||
|                 data->reqdata.resume_from, filesize); |                 data->state.resume_from, filesize); | ||||||
|           return CURLE_BAD_DOWNLOAD_RESUME; |           return CURLE_BAD_DOWNLOAD_RESUME; | ||||||
|         } |         } | ||||||
|         /* convert to size to download */ |         /* convert to size to download */ | ||||||
|         ftp->downloadsize = -data->reqdata.resume_from; |         ftp->downloadsize = -data->state.resume_from; | ||||||
|         /* download from where? */ |         /* download from where? */ | ||||||
|         data->reqdata.resume_from = filesize - ftp->downloadsize; |         data->state.resume_from = filesize - ftp->downloadsize; | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         if(filesize < data->reqdata.resume_from) { |         if(filesize < data->state.resume_from) { | ||||||
|           failf(data, "Offset (%" FORMAT_OFF_T |           failf(data, "Offset (%" FORMAT_OFF_T | ||||||
|                 ") was beyond file size (%" FORMAT_OFF_T ")", |                 ") was beyond file size (%" FORMAT_OFF_T ")", | ||||||
|                 data->reqdata.resume_from, filesize); |                 data->state.resume_from, filesize); | ||||||
|           return CURLE_BAD_DOWNLOAD_RESUME; |           return CURLE_BAD_DOWNLOAD_RESUME; | ||||||
|         } |         } | ||||||
|         /* Now store the number of bytes we are expected to download */ |         /* Now store the number of bytes we are expected to download */ | ||||||
|         ftp->downloadsize = filesize-data->reqdata.resume_from; |         ftp->downloadsize = filesize-data->state.resume_from; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2147,7 +2165,7 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn, | |||||||
|       result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); |       result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); | ||||||
|       infof(data, "File already completely downloaded\n"); |       infof(data, "File already completely downloaded\n"); | ||||||
|  |  | ||||||
|       /* Set ->transfer so that we won't get any error in Curl_ftp_done() |       /* Set ->transfer so that we won't get any error in ftp_done() | ||||||
|        * because we didn't transfer the any file */ |        * because we didn't transfer the any file */ | ||||||
|       ftp->transfer = FTPTRANSFER_NONE; |       ftp->transfer = FTPTRANSFER_NONE; | ||||||
|       state(conn, FTP_STOP); |       state(conn, FTP_STOP); | ||||||
| @@ -2156,9 +2174,9 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn, | |||||||
|  |  | ||||||
|     /* Set resume file transfer offset */ |     /* Set resume file transfer offset */ | ||||||
|     infof(data, "Instructs server to resume from offset %" FORMAT_OFF_T |     infof(data, "Instructs server to resume from offset %" FORMAT_OFF_T | ||||||
|           "\n", data->reqdata.resume_from); |           "\n", data->state.resume_from); | ||||||
|  |  | ||||||
|     NBFTPSENDF(conn, "REST %" FORMAT_OFF_T, data->reqdata.resume_from); |     NBFTPSENDF(conn, "REST %" FORMAT_OFF_T, data->state.resume_from); | ||||||
|  |  | ||||||
|     state(conn, FTP_RETR_REST); |     state(conn, FTP_RETR_REST); | ||||||
|  |  | ||||||
| @@ -2202,7 +2220,7 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn, | |||||||
|     result = ftp_state_post_retr_size(conn, filesize); |     result = ftp_state_post_retr_size(conn, filesize); | ||||||
|   } |   } | ||||||
|   else if(instate == FTP_STOR_SIZE) { |   else if(instate == FTP_STOR_SIZE) { | ||||||
|     data->reqdata.resume_from = filesize; |     data->state.resume_from = filesize; | ||||||
|     result = ftp_state_ul_setup(conn, TRUE); |     result = ftp_state_ul_setup(conn, TRUE); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -2250,7 +2268,7 @@ static CURLcode ftp_state_stor_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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|  |  | ||||||
|   if(ftpcode>=400) { |   if(ftpcode>=400) { | ||||||
|     failf(data, "Failed FTP upload: %0d", ftpcode); |     failf(data, "Failed FTP upload: %0d", ftpcode); | ||||||
| @@ -2297,7 +2315,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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   char *buf = data->state.buffer; |   char *buf = data->state.buffer; | ||||||
|  |  | ||||||
|   if((ftpcode == 150) || (ftpcode == 125)) { |   if((ftpcode == 150) || (ftpcode == 125)) { | ||||||
| @@ -2384,10 +2402,10 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(size > data->reqdata.maxdownload && data->reqdata.maxdownload > 0) |     if(size > data->req.maxdownload && data->req.maxdownload > 0) | ||||||
|       size = data->reqdata.size = data->reqdata.maxdownload; |       size = data->req.size = data->req.maxdownload; | ||||||
|  |  | ||||||
|     infof(data, "Maxdownload = %" FORMAT_OFF_T "\n", data->reqdata.maxdownload); |     infof(data, "Maxdownload = %" FORMAT_OFF_T "\n", data->req.maxdownload); | ||||||
|  |  | ||||||
|     if(instate != FTP_LIST) |     if(instate != FTP_LIST) | ||||||
|       infof(data, "Getting file with size: %" FORMAT_OFF_T "\n", size); |       infof(data, "Getting file with size: %" FORMAT_OFF_T "\n", size); | ||||||
| @@ -2465,7 +2483,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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   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 */ | ||||||
|  |  | ||||||
| @@ -2612,7 +2630,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) | |||||||
|           ftpc->count1 = 1; |           ftpc->count1 = 1; | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d\n", |           failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", | ||||||
|                 data->set.ftpsslauth); |                 data->set.ftpsslauth); | ||||||
|           return CURLE_FAILED_INIT; /* we don't know what to do */ |           return CURLE_FAILED_INIT; /* we don't know what to do */ | ||||||
|         } |         } | ||||||
| @@ -2929,7 +2947,7 @@ static long ftp_state_timeout(struct connectdata *conn) | |||||||
|  |  | ||||||
|  |  | ||||||
| /* called repeatedly until done from multi.c */ | /* called repeatedly until done from multi.c */ | ||||||
| static CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, | static CURLcode ftp_multi_statemach(struct connectdata *conn, | ||||||
|                                          bool *done) |                                          bool *done) | ||||||
| { | { | ||||||
|   curl_socket_t sock = conn->sock[FIRSTSOCKET]; |   curl_socket_t sock = conn->sock[FIRSTSOCKET]; | ||||||
| @@ -3009,17 +3027,17 @@ static CURLcode ftp_init(struct connectdata *conn) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct FTP *ftp; |   struct FTP *ftp; | ||||||
|   if(data->reqdata.proto.ftp) |   if(data->state.proto.ftp) | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|  |  | ||||||
|   ftp = (struct FTP *)calloc(sizeof(struct FTP), 1); |   ftp = (struct FTP *)calloc(sizeof(struct FTP), 1); | ||||||
|   if(!ftp) |   if(!ftp) | ||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   data->reqdata.proto.ftp = ftp; |   data->state.proto.ftp = ftp; | ||||||
|  |  | ||||||
|   /* get some initial data into the ftp struct */ |   /* get some initial data into the ftp struct */ | ||||||
|   ftp->bytecountp = &data->reqdata.keep.bytecount; |   ftp->bytecountp = &data->req.bytecount; | ||||||
|  |  | ||||||
|   /* no need to duplicate them, this connectdata struct won't change */ |   /* no need to duplicate them, this connectdata struct won't change */ | ||||||
|   ftp->user = conn->user; |   ftp->user = conn->user; | ||||||
| @@ -3031,14 +3049,14 @@ static CURLcode ftp_init(struct connectdata *conn) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_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. | ||||||
|  * |  * | ||||||
|  * The variable 'done' points to will be TRUE if the protocol-layer connect |  * The variable 'done' points to will be TRUE if the protocol-layer connect | ||||||
|  * phase is done when this function returns, or FALSE is not. When called as |  * phase is done when this function returns, or FALSE is not. When called as | ||||||
|  * a part of the easy interface, it will always be TRUE. |  * a part of the easy interface, it will always be TRUE. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_ftp_connect(struct connectdata *conn, | static CURLcode ftp_connect(struct connectdata *conn, | ||||||
|                                  bool *done) /* see description above */ |                                  bool *done) /* see description above */ | ||||||
| { | { | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
| @@ -3076,14 +3094,14 @@ static CURLcode Curl_ftp_connect(struct connectdata *conn, | |||||||
|      * Curl_proxyCONNECT we have to set back the member to the original struct |      * Curl_proxyCONNECT we have to set back the member to the original struct | ||||||
|      * FTP pointer |      * FTP pointer | ||||||
|      */ |      */ | ||||||
|     ftp_save = data->reqdata.proto.ftp; |     ftp_save = data->state.proto.ftp; | ||||||
|     memset(&http_proxy, 0, sizeof(http_proxy)); |     memset(&http_proxy, 0, sizeof(http_proxy)); | ||||||
|     data->reqdata.proto.http = &http_proxy; |     data->state.proto.http = &http_proxy; | ||||||
|  |  | ||||||
|     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, |     result = Curl_proxyCONNECT(conn, FIRSTSOCKET, | ||||||
|                                conn->host.name, conn->remote_port); |                                conn->host.name, conn->remote_port); | ||||||
|  |  | ||||||
|     data->reqdata.proto.ftp = ftp_save; |     data->state.proto.ftp = ftp_save; | ||||||
|  |  | ||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
| @@ -3106,7 +3124,7 @@ static CURLcode Curl_ftp_connect(struct connectdata *conn, | |||||||
|   ftpc->response = Curl_tvnow(); /* start response time-out now! */ |   ftpc->response = Curl_tvnow(); /* start response time-out now! */ | ||||||
|  |  | ||||||
|   if(data->state.used_interface == Curl_if_multi) |   if(data->state.used_interface == Curl_if_multi) | ||||||
|     result = Curl_ftp_multi_statemach(conn, done); |     result = ftp_multi_statemach(conn, done); | ||||||
|   else { |   else { | ||||||
|     result = ftp_easy_statemach(conn); |     result = ftp_easy_statemach(conn); | ||||||
|     if(!result) |     if(!result) | ||||||
| @@ -3118,26 +3136,25 @@ static CURLcode Curl_ftp_connect(struct connectdata *conn, | |||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
|  * |  * | ||||||
|  * Curl_ftp_done() |  * ftp_done() | ||||||
|  * |  * | ||||||
|  * The DONE function. This does what needs to be done after a single DO has |  * The DONE function. This does what needs to be done after a single DO has | ||||||
|  * performed. |  * performed. | ||||||
|  * |  * | ||||||
|  * Input argument is already checked for validity. |  * Input argument is already checked for validity. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, | 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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
|   int ftpcode; |   int ftpcode; | ||||||
|   CURLcode result=CURLE_OK; |   CURLcode result=CURLE_OK; | ||||||
|   bool was_ctl_valid = ftpc->ctl_valid; |   bool was_ctl_valid = ftpc->ctl_valid; | ||||||
|   char *path; |   char *path; | ||||||
|   char *path_to_use = data->reqdata.path; |   char *path_to_use = data->state.path; | ||||||
|   struct Curl_transfer_keeper *k = &data->reqdata.keep; |  | ||||||
|  |  | ||||||
|   if(!ftp) |   if(!ftp) | ||||||
|     /* When the easy handle is removed from the multi while libcurl is still |     /* When the easy handle is removed from the multi while libcurl is still | ||||||
| @@ -3281,22 +3298,24 @@ static CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     if((-1 != k->size) && (k->size != *ftp->bytecountp) && |     if((-1 != data->req.size) && | ||||||
|  |        (data->req.size != *ftp->bytecountp) && | ||||||
| #ifdef CURL_DO_LINEEND_CONV | #ifdef CURL_DO_LINEEND_CONV | ||||||
|        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so |        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so | ||||||
|         * we'll check to see if the discrepancy can be explained by the number |         * we'll check to see if the discrepancy can be explained by the number | ||||||
|         * of CRLFs we've changed to LFs. |         * of CRLFs we've changed to LFs. | ||||||
|         */ |         */ | ||||||
|        ((k->size + data->state.crlf_conversions) != *ftp->bytecountp) && |        ((data->req.size + data->state.crlf_conversions) != | ||||||
|  |         *ftp->bytecountp) && | ||||||
| #endif /* CURL_DO_LINEEND_CONV */ | #endif /* CURL_DO_LINEEND_CONV */ | ||||||
|        (k->maxdownload != *ftp->bytecountp)) { |        (data->req.maxdownload != *ftp->bytecountp)) { | ||||||
|       failf(data, "Received only partial file: %" FORMAT_OFF_T " bytes", |       failf(data, "Received only partial file: %" FORMAT_OFF_T " bytes", | ||||||
|             *ftp->bytecountp); |             *ftp->bytecountp); | ||||||
|       result = CURLE_PARTIAL_FILE; |       result = CURLE_PARTIAL_FILE; | ||||||
|     } |     } | ||||||
|     else if(!ftpc->dont_check && |     else if(!ftpc->dont_check && | ||||||
|             !*ftp->bytecountp && |             !*ftp->bytecountp && | ||||||
|             (k->size>0)) { |             (data->req.size>0)) { | ||||||
|       failf(data, "No data was received!"); |       failf(data, "No data was received!"); | ||||||
|       result = CURLE_FTP_COULDNT_RETR_FILE; |       result = CURLE_FTP_COULDNT_RETR_FILE; | ||||||
|     } |     } | ||||||
| @@ -3426,8 +3445,8 @@ static CURLcode ftp_range(struct connectdata *conn) | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if(data->reqdata.use_range && data->reqdata.range) { |   if(data->state.use_range && data->state.range) { | ||||||
|     from=curlx_strtoofft(data->reqdata.range, &ptr, 0); |     from=curlx_strtoofft(data->state.range, &ptr, 0); | ||||||
|     while(ptr && *ptr && (ISSPACE(*ptr) || (*ptr=='-'))) |     while(ptr && *ptr && (ISSPACE(*ptr) || (*ptr=='-'))) | ||||||
|       ptr++; |       ptr++; | ||||||
|     to=curlx_strtoofft(ptr, &ptr2, 0); |     to=curlx_strtoofft(ptr, &ptr2, 0); | ||||||
| @@ -3437,53 +3456,53 @@ static CURLcode ftp_range(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|     if((-1 == to) && (from>=0)) { |     if((-1 == to) && (from>=0)) { | ||||||
|       /* X - */ |       /* X - */ | ||||||
|       data->reqdata.resume_from = from; |       data->state.resume_from = from; | ||||||
|       DEBUGF(infof(conn->data, "FTP RANGE %" FORMAT_OFF_T " to end of file\n", |       DEBUGF(infof(conn->data, "FTP RANGE %" FORMAT_OFF_T " to end of file\n", | ||||||
|                    from)); |                    from)); | ||||||
|     } |     } | ||||||
|     else if(from < 0) { |     else if(from < 0) { | ||||||
|       /* -Y */ |       /* -Y */ | ||||||
|       totalsize = -from; |       totalsize = -from; | ||||||
|       data->reqdata.maxdownload = -from; |       data->req.maxdownload = -from; | ||||||
|       data->reqdata.resume_from = from; |       data->state.resume_from = from; | ||||||
|       DEBUGF(infof(conn->data, "FTP RANGE the last %" FORMAT_OFF_T " bytes\n", |       DEBUGF(infof(conn->data, "FTP RANGE the last %" FORMAT_OFF_T " bytes\n", | ||||||
|                    totalsize)); |                    totalsize)); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       /* X-Y */ |       /* X-Y */ | ||||||
|       totalsize = to-from; |       totalsize = to-from; | ||||||
|       data->reqdata.maxdownload = totalsize+1; /* include last byte */ |       data->req.maxdownload = totalsize+1; /* include last byte */ | ||||||
|       data->reqdata.resume_from = from; |       data->state.resume_from = from; | ||||||
|       DEBUGF(infof(conn->data, "FTP RANGE from %" FORMAT_OFF_T |       DEBUGF(infof(conn->data, "FTP RANGE from %" FORMAT_OFF_T | ||||||
|                    " getting %" FORMAT_OFF_T " bytes\n", |                    " getting %" FORMAT_OFF_T " bytes\n", | ||||||
|                    from, data->reqdata.maxdownload)); |                    from, data->req.maxdownload)); | ||||||
|     } |     } | ||||||
|     DEBUGF(infof(conn->data, "range-download from %" FORMAT_OFF_T |     DEBUGF(infof(conn->data, "range-download from %" FORMAT_OFF_T | ||||||
|                  " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", |                  " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", | ||||||
|                  from, to, data->reqdata.maxdownload)); |                  from, to, data->req.maxdownload)); | ||||||
|     ftpc->dont_check = TRUE; /* dont check for successful transfer */ |     ftpc->dont_check = TRUE; /* dont check for successful transfer */ | ||||||
|   } |   } | ||||||
|   else |   else | ||||||
|     data->reqdata.maxdownload = -1; |     data->req.maxdownload = -1; | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_ftp_nextconnect() |  * ftp_nextconnect() | ||||||
|  * |  * | ||||||
|  * This function shall be called when the second FTP (data) connection is |  * This function shall be called when the second FTP (data) connection is | ||||||
|  * connected. |  * connected. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static CURLcode Curl_ftp_nextconnect(struct connectdata *conn) | static CURLcode ftp_nextconnect(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|  |  | ||||||
|   /* the ftp struct is inited in Curl_ftp_connect() */ |   /* the ftp struct is inited in ftp_connect() */ | ||||||
|   struct FTP *ftp = data->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|  |  | ||||||
|   DEBUGF(infof(data, "DO-MORE phase starts\n")); |   DEBUGF(infof(data, "DO-MORE phase starts\n")); | ||||||
|  |  | ||||||
| @@ -3525,7 +3544,7 @@ static CURLcode Curl_ftp_nextconnect(struct connectdata *conn) | |||||||
|     result = ftp_easy_statemach(conn); |     result = ftp_easy_statemach(conn); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(ftp->transfer != FTPTRANSFER_BODY) |   if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY)) | ||||||
|     /* no data to transfer. FIX: it feels like a kludge to have this here |     /* no data to transfer. FIX: it feels like a kludge to have this here | ||||||
|        too! */ |        too! */ | ||||||
|     result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); |     result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); | ||||||
| @@ -3558,7 +3577,7 @@ CURLcode ftp_perform(struct connectdata *conn, | |||||||
|  |  | ||||||
|   if(conn->bits.no_body) { |   if(conn->bits.no_body) { | ||||||
|     /* requested no body means no transfer... */ |     /* requested no body means no transfer... */ | ||||||
|     struct FTP *ftp = conn->data->reqdata.proto.ftp; |     struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|     ftp->transfer = FTPTRANSFER_INFO; |     ftp->transfer = FTPTRANSFER_INFO; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -3572,7 +3591,7 @@ CURLcode ftp_perform(struct connectdata *conn, | |||||||
|  |  | ||||||
|   /* run the state-machine */ |   /* run the state-machine */ | ||||||
|   if(conn->data->state.used_interface == Curl_if_multi) |   if(conn->data->state.used_interface == Curl_if_multi) | ||||||
|     result = Curl_ftp_multi_statemach(conn, dophase_done); |     result = ftp_multi_statemach(conn, dophase_done); | ||||||
|   else { |   else { | ||||||
|     result = ftp_easy_statemach(conn); |     result = ftp_easy_statemach(conn); | ||||||
|     *dophase_done = TRUE; /* with the easy interface we are done here */ |     *dophase_done = TRUE; /* with the easy interface we are done here */ | ||||||
| @@ -3587,14 +3606,14 @@ CURLcode ftp_perform(struct connectdata *conn, | |||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
|  * |  * | ||||||
|  * Curl_ftp() |  * ftp_do() | ||||||
|  * |  * | ||||||
|  * This function is registered as 'curl_do' function. It decodes the path |  * This function is registered as 'curl_do' function. It decodes the path | ||||||
|  * parts etc as a wrapper to the actual DO function (ftp_perform). |  * parts etc as a wrapper to the actual DO function (ftp_perform). | ||||||
|  * |  * | ||||||
|  * The input argument is already checked for validity. |  * The input argument is already checked for validity. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_ftp(struct connectdata *conn, bool *done) | static CURLcode ftp_do(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
|   CURLcode retcode = CURLE_OK; |   CURLcode retcode = CURLE_OK; | ||||||
|  |  | ||||||
| @@ -3604,7 +3623,7 @@ static CURLcode Curl_ftp(struct connectdata *conn, bool *done) | |||||||
|     Since connections can be re-used between SessionHandles, this might be a |     Since connections can be re-used between SessionHandles, this might be a | ||||||
|     connection already existing but on a fresh SessionHandle struct so we must |     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, |     make sure we have a good 'struct FTP' to play with. For new connections, | ||||||
|     the struct FTP is allocated and setup in the Curl_ftp_connect() function. |     the struct FTP is allocated and setup in the ftp_connect() function. | ||||||
|   */ |   */ | ||||||
|   Curl_reset_reqproto(conn); |   Curl_reset_reqproto(conn); | ||||||
|   retcode = ftp_init(conn); |   retcode = ftp_init(conn); | ||||||
| @@ -3787,12 +3806,12 @@ static CURLcode ftp_quit(struct connectdata *conn) | |||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
|  * |  * | ||||||
|  * Curl_ftp_disconnect() |  * ftp_disconnect() | ||||||
|  * |  * | ||||||
|  * Disconnect from an FTP server. Cleanup protocol-specific per-connection |  * Disconnect from an FTP server. Cleanup protocol-specific per-connection | ||||||
|  * resources. BLOCKING. |  * resources. BLOCKING. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_ftp_disconnect(struct connectdata *conn) | static CURLcode ftp_disconnect(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct ftp_conn *ftpc= &conn->proto.ftpc; |   struct ftp_conn *ftpc= &conn->proto.ftpc; | ||||||
|  |  | ||||||
| @@ -3840,11 +3859,11 @@ 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->reqdata.proto.ftp; |   struct FTP *ftp = data->state.proto.ftp; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   size_t dlen; |   size_t dlen; | ||||||
|   char *slash_pos;  /* position of the first '/' char in curpos */ |   char *slash_pos;  /* position of the first '/' char in curpos */ | ||||||
|   char *path_to_use = data->reqdata.path; |   char *path_to_use = data->state.path; | ||||||
|   char *cur_pos; |   char *cur_pos; | ||||||
|  |  | ||||||
|   cur_pos = path_to_use; /* current position in path. point at the begin |   cur_pos = path_to_use; /* current position in path. point at the begin | ||||||
| @@ -3864,10 +3883,10 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
|       the first condition in the if() right here, is there just in case |       the first condition in the if() right here, is there just in case | ||||||
|       someone decides to set path to NULL one day |       someone decides to set path to NULL one day | ||||||
|    */ |    */ | ||||||
|     if(data->reqdata.path && |     if(data->state.path && | ||||||
|        data->reqdata.path[0] && |        data->state.path[0] && | ||||||
|        (data->reqdata.path[strlen(data->reqdata.path) - 1] != '/') ) |        (data->state.path[strlen(data->state.path) - 1] != '/') ) | ||||||
|       ftpc->file = data->reqdata.path;  /* this is a full file path */ |       ftpc->file = data->state.path;  /* this is a full file path */ | ||||||
|     else |     else | ||||||
|       ftpc->file = NULL; |       ftpc->file = NULL; | ||||||
|       /* |       /* | ||||||
| @@ -3924,7 +3943,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
|       /* parse the URL path into separate path components */ |       /* parse the URL path into separate path components */ | ||||||
|       while((slash_pos = strchr(cur_pos, '/')) != NULL) { |       while((slash_pos = strchr(cur_pos, '/')) != NULL) { | ||||||
|         /* 1 or 0 to indicate absolute directory */ |         /* 1 or 0 to indicate absolute directory */ | ||||||
|         bool absolute_dir = (bool)((cur_pos - data->reqdata.path > 0) && |         bool absolute_dir = (bool)((cur_pos - data->state.path > 0) && | ||||||
|                                    (ftpc->dirdepth == 0)); |                                    (ftpc->dirdepth == 0)); | ||||||
|  |  | ||||||
|         /* seek out the next path component */ |         /* seek out the next path component */ | ||||||
| @@ -3995,7 +4014,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) | |||||||
|   if(ftpc->prevpath) { |   if(ftpc->prevpath) { | ||||||
|     /* prevpath is "raw" so we convert the input path before we compare the |     /* prevpath is "raw" so we convert the input path before we compare the | ||||||
|        strings */ |        strings */ | ||||||
|     char *path = curl_easy_unescape(conn->data, data->reqdata.path, 0, NULL); |     char *path = curl_easy_unescape(conn->data, data->state.path, 0, NULL); | ||||||
|     if(!path) { |     if(!path) { | ||||||
|       freedirs(ftpc); |       freedirs(ftpc); | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
| @@ -4018,11 +4037,11 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, | |||||||
|                                  bool connected) |                                  bool connected) | ||||||
| { | { | ||||||
|   CURLcode result = CURLE_OK; |   CURLcode result = CURLE_OK; | ||||||
|   struct FTP *ftp = conn->data->reqdata.proto.ftp; |   struct FTP *ftp = conn->data->state.proto.ftp; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|  |  | ||||||
|   if(connected) |   if(connected) | ||||||
|     result = Curl_ftp_nextconnect(conn); |     result = ftp_nextconnect(conn); | ||||||
|  |  | ||||||
|   if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) { |   if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) { | ||||||
|     /* Failure detected, close the second socket if it was created already */ |     /* Failure detected, close the second socket if it was created already */ | ||||||
| @@ -4044,11 +4063,11 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, | |||||||
| } | } | ||||||
|  |  | ||||||
| /* called from multi.c while DOing */ | /* called from multi.c while DOing */ | ||||||
| static CURLcode Curl_ftp_doing(struct connectdata *conn, | static CURLcode ftp_doing(struct connectdata *conn, | ||||||
|                                bool *dophase_done) |                                bool *dophase_done) | ||||||
| { | { | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|   result = Curl_ftp_multi_statemach(conn, dophase_done); |   result = ftp_multi_statemach(conn, dophase_done); | ||||||
|  |  | ||||||
|   if(*dophase_done) { |   if(*dophase_done) { | ||||||
|     result = ftp_dophase_done(conn, FALSE /* not connected */); |     result = ftp_dophase_done(conn, FALSE /* not connected */); | ||||||
| @@ -4068,7 +4087,7 @@ static CURLcode Curl_ftp_doing(struct connectdata *conn, | |||||||
|  * remote host. |  * remote host. | ||||||
|  * |  * | ||||||
|  * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the |  * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the | ||||||
|  * Curl_ftp_done() function without finding any major problem. |  * ftp_done() function without finding any major problem. | ||||||
|  */ |  */ | ||||||
| static | static | ||||||
| CURLcode ftp_regular_transfer(struct connectdata *conn, | CURLcode ftp_regular_transfer(struct connectdata *conn, | ||||||
| @@ -4078,7 +4097,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn, | |||||||
|   bool connected=0; |   bool connected=0; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct ftp_conn *ftpc = &conn->proto.ftpc; |   struct ftp_conn *ftpc = &conn->proto.ftpc; | ||||||
|   data->reqdata.size = -1; /* make sure this is unknown at this point */ |   data->req.size = -1; /* make sure this is unknown at this point */ | ||||||
|  |  | ||||||
|   Curl_pgrsSetUploadCounter(data, 0); |   Curl_pgrsSetUploadCounter(data, 0); | ||||||
|   Curl_pgrsSetDownloadCounter(data, 0); |   Curl_pgrsSetDownloadCounter(data, 0); | ||||||
| @@ -4107,7 +4126,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn, | |||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| static CURLcode Curl_ftp_setup_connection(struct connectdata * conn) | static CURLcode ftp_setup_connection(struct connectdata * conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   char * type; |   char * type; | ||||||
| @@ -4134,11 +4153,11 @@ static CURLcode Curl_ftp_setup_connection(struct connectdata * conn) | |||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   data->reqdata.path++;   /* don't include the initial slash */ |   data->state.path++;   /* don't include the initial slash */ | ||||||
|  |  | ||||||
|   /* FTP URLs support an extension like ";type=<typecode>" that |   /* FTP URLs support an extension like ";type=<typecode>" that | ||||||
|    * we'll try to get now! */ |    * we'll try to get now! */ | ||||||
|   type = strstr(data->reqdata.path, ";type="); |   type = strstr(data->state.path, ";type="); | ||||||
|  |  | ||||||
|   if(!type) |   if(!type) | ||||||
|     type = strstr(conn->host.rawalloc, ";type="); |     type = strstr(conn->host.rawalloc, ";type="); | ||||||
| @@ -4168,12 +4187,12 @@ static CURLcode Curl_ftp_setup_connection(struct connectdata * conn) | |||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef USE_SSL | #ifdef USE_SSL | ||||||
| static CURLcode Curl_ftps_setup_connection(struct connectdata * conn) | static CURLcode ftps_setup_connection(struct connectdata * conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|   conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLUSESSL_CONTROL; |   conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLUSESSL_CONTROL; | ||||||
|   return Curl_ftp_setup_connection(conn); |   return ftp_setup_connection(conn); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								lib/hostip.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								lib/hostip.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -127,22 +127,19 @@ static void freednsentry(void *freethis); | |||||||
|  * Curl_global_host_cache_init() initializes and sets up a global DNS cache. |  * Curl_global_host_cache_init() initializes and sets up a global DNS cache. | ||||||
|  * Global DNS cache is general badness. Do not use. This will be removed in |  * Global DNS cache is general badness. Do not use. This will be removed in | ||||||
|  * a future version. Use the share interface instead! |  * a future version. Use the share interface instead! | ||||||
|  |  * | ||||||
|  |  * Returns a struct curl_hash pointer on success, NULL on failure. | ||||||
|  */ |  */ | ||||||
| void Curl_global_host_cache_init(void) | struct curl_hash *Curl_global_host_cache_init(void) | ||||||
| { | { | ||||||
|  |   int rc = 0; | ||||||
|   if(!host_cache_initialized) { |   if(!host_cache_initialized) { | ||||||
|     Curl_hash_init(&hostname_cache, 7, Curl_hash_str, Curl_str_key_compare, |     rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str, | ||||||
|                    freednsentry); |                         Curl_str_key_compare, freednsentry); | ||||||
|  |     if(!rc) | ||||||
|       host_cache_initialized = 1; |       host_cache_initialized = 1; | ||||||
|   } |   } | ||||||
| } |   return rc?NULL:&hostname_cache; | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Return a pointer to the global cache |  | ||||||
|  */ |  | ||||||
| struct curl_hash *Curl_global_host_cache_get(void) |  | ||||||
| { |  | ||||||
|   return &hostname_cache; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								lib/hostip.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								lib/hostip.h
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -125,11 +125,15 @@ struct hostent; | |||||||
| struct SessionHandle; | struct SessionHandle; | ||||||
| struct connectdata; | struct connectdata; | ||||||
|  |  | ||||||
| void Curl_global_host_cache_init(void); | /* | ||||||
|  |  * Curl_global_host_cache_init() initializes and sets up a global DNS cache. | ||||||
|  |  * Global DNS cache is general badness. Do not use. This will be removed in | ||||||
|  |  * a future version. Use the share interface instead! | ||||||
|  |  * | ||||||
|  |  * Returns a struct curl_hash pointer on success, NULL on failure. | ||||||
|  |  */ | ||||||
|  | struct curl_hash *Curl_global_host_cache_init(void); | ||||||
| void Curl_global_host_cache_dtor(void); | void Curl_global_host_cache_dtor(void); | ||||||
| struct curl_hash *Curl_global_host_cache_get(void); |  | ||||||
|  |  | ||||||
| #define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache) |  | ||||||
|  |  | ||||||
| struct Curl_dns_entry { | struct Curl_dns_entry { | ||||||
|   Curl_addrinfo *addr; |   Curl_addrinfo *addr; | ||||||
|   | |||||||
							
								
								
									
										277
									
								
								lib/http.c
									
									
									
									
									
								
							
							
						
						
									
										277
									
								
								lib/http.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -109,9 +109,9 @@ | |||||||
|  * Forward declarations. |  * Forward declarations. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done); | static CURLcode https_connecting(struct connectdata *conn, bool *done); | ||||||
| #ifdef USE_SSL | #ifdef USE_SSL | ||||||
| static int Curl_https_getsock(struct connectdata *conn, | static int https_getsock(struct connectdata *conn, | ||||||
|                               curl_socket_t *socks, |                               curl_socket_t *socks, | ||||||
|                               int numsocks); |                               int numsocks); | ||||||
| #endif | #endif | ||||||
| @@ -146,9 +146,9 @@ const struct Curl_handler Curl_handler_https = { | |||||||
|   Curl_http_done,                       /* done */ |   Curl_http_done,                       /* done */ | ||||||
|   ZERO_NULL,                            /* do_more */ |   ZERO_NULL,                            /* do_more */ | ||||||
|   Curl_http_connect,                    /* connect_it */ |   Curl_http_connect,                    /* connect_it */ | ||||||
|   Curl_https_connecting,                /* connecting */ |   https_connecting,                /* connecting */ | ||||||
|   ZERO_NULL,                            /* doing */ |   ZERO_NULL,                            /* doing */ | ||||||
|   Curl_https_getsock,                   /* proto_getsock */ |   https_getsock,                   /* proto_getsock */ | ||||||
|   ZERO_NULL,                            /* doing_getsock */ |   ZERO_NULL,                            /* doing_getsock */ | ||||||
|   ZERO_NULL,                            /* disconnect */ |   ZERO_NULL,                            /* disconnect */ | ||||||
|   PORT_HTTPS,                           /* defport */ |   PORT_HTTPS,                           /* defport */ | ||||||
| @@ -176,12 +176,12 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Curl_output_basic() sets up an Authorization: header (or the proxy version) |  * http_output_basic() sets up an Authorization: header (or the proxy version) | ||||||
|  * for HTTP Basic authentication. |  * for HTTP Basic authentication. | ||||||
|  * |  * | ||||||
|  * Returns CURLcode. |  * Returns CURLcode. | ||||||
|  */ |  */ | ||||||
| static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy) | static CURLcode http_output_basic(struct connectdata *conn, bool proxy) | ||||||
| { | { | ||||||
|   char *authorization; |   char *authorization; | ||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
| @@ -275,8 +275,7 @@ static bool pickoneauth(struct auth *pick) | |||||||
| static CURLcode perhapsrewind(struct connectdata *conn) | static CURLcode perhapsrewind(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct HTTP *http = data->reqdata.proto.http; |   struct HTTP *http = data->state.proto.http; | ||||||
|   struct Curl_transfer_keeper *k = &data->reqdata.keep; |  | ||||||
|   curl_off_t bytessent; |   curl_off_t bytessent; | ||||||
|   curl_off_t expectsend = -1; /* default is unknown */ |   curl_off_t expectsend = -1; /* default is unknown */ | ||||||
|  |  | ||||||
| @@ -338,7 +337,7 @@ static CURLcode perhapsrewind(struct connectdata *conn) | |||||||
|     /* This is not NTLM or NTLM with many bytes left to send: close |     /* This is not NTLM or NTLM with many bytes left to send: close | ||||||
|      */ |      */ | ||||||
|     conn->bits.close = TRUE; |     conn->bits.close = TRUE; | ||||||
|     k->size = 0; /* don't download any more than 0 bytes */ |     data->req.size = 0; /* don't download any more than 0 bytes */ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(bytessent) |   if(bytessent) | ||||||
| @@ -361,7 +360,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) | |||||||
|   bool pickproxy = FALSE; |   bool pickproxy = FALSE; | ||||||
|   CURLcode code = CURLE_OK; |   CURLcode code = CURLE_OK; | ||||||
|  |  | ||||||
|   if(100 == data->reqdata.keep.httpcode) |   if(100 == data->req.httpcode) | ||||||
|     /* this is a transient response code, ignore */ |     /* this is a transient response code, ignore */ | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|  |  | ||||||
| @@ -369,23 +368,23 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) | |||||||
|     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; |     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; | ||||||
|  |  | ||||||
|   if(conn->bits.user_passwd && |   if(conn->bits.user_passwd && | ||||||
|      ((data->reqdata.keep.httpcode == 401) || |      ((data->req.httpcode == 401) || | ||||||
|       (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { |       (conn->bits.authneg && data->req.httpcode < 300))) { | ||||||
|     pickhost = pickoneauth(&data->state.authhost); |     pickhost = pickoneauth(&data->state.authhost); | ||||||
|     if(!pickhost) |     if(!pickhost) | ||||||
|       data->state.authproblem = TRUE; |       data->state.authproblem = TRUE; | ||||||
|   } |   } | ||||||
|   if(conn->bits.proxy_user_passwd && |   if(conn->bits.proxy_user_passwd && | ||||||
|      ((data->reqdata.keep.httpcode == 407) || |      ((data->req.httpcode == 407) || | ||||||
|       (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) { |       (conn->bits.authneg && data->req.httpcode < 300))) { | ||||||
|     pickproxy = pickoneauth(&data->state.authproxy); |     pickproxy = pickoneauth(&data->state.authproxy); | ||||||
|     if(!pickproxy) |     if(!pickproxy) | ||||||
|       data->state.authproblem = TRUE; |       data->state.authproblem = TRUE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(pickhost || pickproxy) { |   if(pickhost || pickproxy) { | ||||||
|     data->reqdata.newurl = strdup(data->change.url); /* clone URL */ |     data->req.newurl = strdup(data->change.url); /* clone URL */ | ||||||
|     if (!data->reqdata.newurl) |     if(!data->req.newurl) | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|     if((data->set.httpreq != HTTPREQ_GET) && |     if((data->set.httpreq != HTTPREQ_GET) && | ||||||
| @@ -397,7 +396,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   else if((data->reqdata.keep.httpcode < 300) && |   else if((data->req.httpcode < 300) && | ||||||
|           (!data->state.authhost.done) && |           (!data->state.authhost.done) && | ||||||
|           conn->bits.authneg) { |           conn->bits.authneg) { | ||||||
|     /* no (known) authentication available, |     /* no (known) authentication available, | ||||||
| @@ -406,15 +405,15 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) | |||||||
|        we didn't try HEAD or GET */ |        we didn't try HEAD or GET */ | ||||||
|     if((data->set.httpreq != HTTPREQ_GET) && |     if((data->set.httpreq != HTTPREQ_GET) && | ||||||
|        (data->set.httpreq != HTTPREQ_HEAD)) { |        (data->set.httpreq != HTTPREQ_HEAD)) { | ||||||
|       data->reqdata.newurl = strdup(data->change.url); /* clone URL */ |       data->req.newurl = strdup(data->change.url); /* clone URL */ | ||||||
|       if (!data->reqdata.newurl) |       if(!data->req.newurl) | ||||||
|         return CURLE_OUT_OF_MEMORY; |         return CURLE_OUT_OF_MEMORY; | ||||||
|       data->state.authhost.done = TRUE; |       data->state.authhost.done = TRUE; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if(Curl_http_should_fail(conn)) { |   if(Curl_http_should_fail(conn)) { | ||||||
|     failf (data, "The requested URL returned error: %d", |     failf (data, "The requested URL returned error: %d", | ||||||
|            data->reqdata.keep.httpcode); |            data->req.httpcode); | ||||||
|     code = CURLE_HTTP_RETURNED_ERROR; |     code = CURLE_HTTP_RETURNED_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -436,7 +435,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) | |||||||
|  * @returns CURLcode |  * @returns CURLcode | ||||||
|  */ |  */ | ||||||
| static CURLcode | static CURLcode | ||||||
| Curl_http_output_auth(struct connectdata *conn, | http_output_auth(struct connectdata *conn, | ||||||
|                  const char *request, |                  const char *request, | ||||||
|                  const char *path, |                  const char *path, | ||||||
|                  bool proxytunnel) /* TRUE if this is the request setting |                  bool proxytunnel) /* TRUE if this is the request setting | ||||||
| @@ -503,11 +502,11 @@ Curl_http_output_auth(struct connectdata *conn, | |||||||
|         if(conn->bits.proxy_user_passwd && |         if(conn->bits.proxy_user_passwd && | ||||||
|            !checkheaders(data, "Proxy-authorization:")) { |            !checkheaders(data, "Proxy-authorization:")) { | ||||||
|           auth="Basic"; |           auth="Basic"; | ||||||
|           result = Curl_output_basic(conn, TRUE); |           result = http_output_basic(conn, TRUE); | ||||||
|           if(result) |           if(result) | ||||||
|             return result; |             return result; | ||||||
|         } |         } | ||||||
|         /* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth |         /* NOTE: http_output_basic() should set 'done' TRUE, as the other auth | ||||||
|            functions work that way */ |            functions work that way */ | ||||||
|         authproxy->done = TRUE; |         authproxy->done = TRUE; | ||||||
|       } |       } | ||||||
| @@ -583,7 +582,7 @@ Curl_http_output_auth(struct connectdata *conn, | |||||||
|           if(conn->bits.user_passwd && |           if(conn->bits.user_passwd && | ||||||
|              !checkheaders(data, "Authorization:")) { |              !checkheaders(data, "Authorization:")) { | ||||||
|             auth="Basic"; |             auth="Basic"; | ||||||
|             result = Curl_output_basic(conn, FALSE); |             result = http_output_basic(conn, FALSE); | ||||||
|             if(result) |             if(result) | ||||||
|               return result; |               return result; | ||||||
|           } |           } | ||||||
| @@ -660,8 +659,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
|       /* if exactly this is wanted, go */ |       /* if exactly this is wanted, go */ | ||||||
|       int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); |       int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); | ||||||
|       if(neg == 0) { |       if(neg == 0) { | ||||||
|         data->reqdata.newurl = strdup(data->change.url); |         data->req.newurl = strdup(data->change.url); | ||||||
|         data->state.authproblem = (data->reqdata.newurl == NULL); |         data->state.authproblem = (data->req.newurl == NULL); | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         infof(data, "Authentication problem. Ignoring this.\n"); |         infof(data, "Authentication problem. Ignoring this.\n"); | ||||||
| @@ -743,16 +742,13 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, | |||||||
| int Curl_http_should_fail(struct connectdata *conn) | int Curl_http_should_fail(struct connectdata *conn) | ||||||
| { | { | ||||||
|   struct SessionHandle *data; |   struct SessionHandle *data; | ||||||
|   struct Curl_transfer_keeper *k; |   int httpcode; | ||||||
|  |  | ||||||
|   DEBUGASSERT(conn); |   DEBUGASSERT(conn); | ||||||
|   data = conn->data; |   data = conn->data; | ||||||
|   DEBUGASSERT(data); |   DEBUGASSERT(data); | ||||||
|  |  | ||||||
|   /* |   httpcode = data->req.httpcode; | ||||||
|   ** For readability |  | ||||||
|   */ |  | ||||||
|   k = &data->reqdata.keep; |  | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|   ** If we haven't been asked to fail on error, |   ** If we haven't been asked to fail on error, | ||||||
| @@ -764,12 +760,12 @@ int Curl_http_should_fail(struct connectdata *conn) | |||||||
|   /* |   /* | ||||||
|   ** Any code < 400 is never terminal. |   ** Any code < 400 is never terminal. | ||||||
|   */ |   */ | ||||||
|   if (k->httpcode < 400) |   if(httpcode < 400) | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   if (data->reqdata.resume_from && |   if(data->state.resume_from && | ||||||
|      (data->set.httpreq==HTTPREQ_GET) && |      (data->set.httpreq==HTTPREQ_GET) && | ||||||
|       (k->httpcode == 416)) { |      (httpcode == 416)) { | ||||||
|     /* "Requested Range Not Satisfiable", just proceed and |     /* "Requested Range Not Satisfiable", just proceed and | ||||||
|        pretend this is no error */ |        pretend this is no error */ | ||||||
|     return 0; |     return 0; | ||||||
| @@ -779,14 +775,14 @@ int Curl_http_should_fail(struct connectdata *conn) | |||||||
|   ** Any code >= 400 that's not 401 or 407 is always |   ** Any code >= 400 that's not 401 or 407 is always | ||||||
|   ** a terminal error |   ** a terminal error | ||||||
|   */ |   */ | ||||||
|   if ((k->httpcode != 401) && |   if((httpcode != 401) && | ||||||
|       (k->httpcode != 407)) |       (httpcode != 407)) | ||||||
|     return 1; |     return 1; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|   ** All we have left to deal with is 401 and 407 |   ** All we have left to deal with is 401 and 407 | ||||||
|   */ |   */ | ||||||
|   DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407)); |   DEBUGASSERT((httpcode == 401) || (httpcode == 407)); | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
|   ** Examine the current authentication state to see if this |   ** Examine the current authentication state to see if this | ||||||
| @@ -807,7 +803,8 @@ int Curl_http_should_fail(struct connectdata *conn) | |||||||
|   infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); |   infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); | ||||||
|   infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); |   infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); | ||||||
|   infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); |   infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); | ||||||
|   infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)"); |   infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ? | ||||||
|  |         data->req.newurl : "(null)"); | ||||||
|   infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); |   infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -815,9 +812,9 @@ int Curl_http_should_fail(struct connectdata *conn) | |||||||
|   ** Either we're not authenticating, or we're supposed to |   ** Either we're not authenticating, or we're supposed to | ||||||
|   ** be authenticating something else.  This is an error. |   ** be authenticating something else.  This is an error. | ||||||
|   */ |   */ | ||||||
|   if((k->httpcode == 401) && !conn->bits.user_passwd) |   if((httpcode == 401) && !conn->bits.user_passwd) | ||||||
|     return TRUE; |     return TRUE; | ||||||
|   if((k->httpcode == 407) && !conn->bits.proxy_user_passwd) |   if((httpcode == 407) && !conn->bits.proxy_user_passwd) | ||||||
|     return TRUE; |     return TRUE; | ||||||
|  |  | ||||||
|   return data->state.authproblem; |   return data->state.authproblem; | ||||||
| @@ -837,7 +834,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->reqdata.proto.http; |   struct HTTP *http = conn->data->state.proto.http; | ||||||
|   size_t fullsize = size * nitems; |   size_t fullsize = size * nitems; | ||||||
|  |  | ||||||
|   if(0 == http->postsize) |   if(0 == http->postsize) | ||||||
| @@ -929,9 +926,10 @@ CURLcode add_buffer_send(send_buffer *in, | |||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   char *ptr; |   char *ptr; | ||||||
|   size_t size; |   size_t size; | ||||||
|   struct HTTP *http = conn->data->reqdata.proto.http; |   struct HTTP *http = conn->data->state.proto.http; | ||||||
|   size_t sendsize; |   size_t sendsize; | ||||||
|   curl_socket_t sockfd; |   curl_socket_t sockfd; | ||||||
|  |   size_t headersize; | ||||||
|  |  | ||||||
|   DEBUGASSERT(socketindex <= SECONDARYSOCKET); |   DEBUGASSERT(socketindex <= SECONDARYSOCKET); | ||||||
|  |  | ||||||
| @@ -943,9 +941,13 @@ CURLcode add_buffer_send(send_buffer *in, | |||||||
|   ptr = in->buffer; |   ptr = in->buffer; | ||||||
|   size = in->size_used; |   size = in->size_used; | ||||||
|  |  | ||||||
|  |   headersize = size - included_body_bytes; /* the initial part that isn't body | ||||||
|  |                                               is header */ | ||||||
|  |  | ||||||
|  |   DEBUGASSERT(size > included_body_bytes); | ||||||
|  |  | ||||||
| #ifdef CURL_DOES_CONVERSIONS | #ifdef CURL_DOES_CONVERSIONS | ||||||
|   if(size - included_body_bytes > 0) { |   res = Curl_convert_to_network(conn->data, ptr, headersize); | ||||||
|     res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes); |  | ||||||
|   /* Curl_convert_to_network calls failf if unsuccessful */ |   /* Curl_convert_to_network calls failf if unsuccessful */ | ||||||
|   if(res != CURLE_OK) { |   if(res != CURLE_OK) { | ||||||
|     /* conversion failed, free memory and return to the caller */ |     /* conversion failed, free memory and return to the caller */ | ||||||
| @@ -954,7 +956,6 @@ CURLcode add_buffer_send(send_buffer *in, | |||||||
|     free(in); |     free(in); | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
|   } |  | ||||||
| #endif /* CURL_DOES_CONVERSIONS */ | #endif /* CURL_DOES_CONVERSIONS */ | ||||||
|  |  | ||||||
|   if(conn->protocol & PROT_HTTPS) { |   if(conn->protocol & PROT_HTTPS) { | ||||||
| @@ -981,20 +982,29 @@ CURLcode add_buffer_send(send_buffer *in, | |||||||
|   res = Curl_write(conn, sockfd, ptr, sendsize, &amount); |   res = Curl_write(conn, sockfd, ptr, sendsize, &amount); | ||||||
|  |  | ||||||
|   if(CURLE_OK == res) { |   if(CURLE_OK == res) { | ||||||
|  |     /* | ||||||
|  |      * Note that we may not send the entire chunk at once, and we have a set | ||||||
|  |      * number of data bytes at the end of the big buffer (out of which we may | ||||||
|  |      * only send away a part). | ||||||
|  |      */ | ||||||
|  |     /* how much of the header that was sent */ | ||||||
|  |     size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount; | ||||||
|  |     size_t bodylen = amount - headlen; | ||||||
|  |  | ||||||
|     if(conn->data->set.verbose) { |     if(conn->data->set.verbose) { | ||||||
|       /* this data _may_ contain binary stuff */ |       /* this data _may_ contain binary stuff */ | ||||||
|       Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, |       Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); | ||||||
|                  (size_t)(amount-included_body_bytes), conn); |       if((size_t)amount > headlen) { | ||||||
|       if (included_body_bytes) |         /* there was body data sent beyond the initial header part, pass that | ||||||
|  |            on to the debug callback too */ | ||||||
|         Curl_debug(conn->data, CURLINFO_DATA_OUT, |         Curl_debug(conn->data, CURLINFO_DATA_OUT, | ||||||
|                    ptr+amount-included_body_bytes, |                    ptr+headlen, bodylen, conn); | ||||||
|                    (size_t)included_body_bytes, conn); |  | ||||||
|       } |       } | ||||||
|     if (included_body_bytes) |     } | ||||||
|  |     if(bodylen) | ||||||
|       /* since we sent a piece of the body here, up the byte counter for it |       /* since we sent a piece of the body here, up the byte counter for it | ||||||
|          accordingly */ |          accordingly */ | ||||||
|       http->writebytecount = included_body_bytes; |       http->writebytecount += bodylen; | ||||||
|  |  | ||||||
|     *bytes_written += amount; |     *bytes_written += amount; | ||||||
|  |  | ||||||
| @@ -1083,9 +1093,28 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) | |||||||
|   char *new_rb; |   char *new_rb; | ||||||
|   size_t new_size; |   size_t new_size; | ||||||
|  |  | ||||||
|  |   if(~size < in->size_used) { | ||||||
|  |     /* If resulting used size of send buffer would wrap size_t, cleanup | ||||||
|  |        the whole buffer and return error. Otherwise the required buffer | ||||||
|  |        size will fit into a single allocatable memory chunk */ | ||||||
|  |     Curl_safefree(in->buffer); | ||||||
|  |     free(in); | ||||||
|  |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   if(!in->buffer || |   if(!in->buffer || | ||||||
|      ((in->size_used + size) > (in->size_max - 1))) { |      ((in->size_used + size) > (in->size_max - 1))) { | ||||||
|  |  | ||||||
|  |     /* If current buffer size isn't enough to hold the result, use a | ||||||
|  |        buffer size that doubles the required size. If this new size | ||||||
|  |        would wrap size_t, then just use the largest possible one */ | ||||||
|  |  | ||||||
|  |     if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) || | ||||||
|  |        (~(size*2) < (in->size_used*2))) | ||||||
|  |       new_size = (size_t)-1; | ||||||
|  |     else | ||||||
|       new_size = (in->size_used+size)*2; |       new_size = (in->size_used+size)*2; | ||||||
|  |  | ||||||
|     if(in->buffer) |     if(in->buffer) | ||||||
|       /* we have a buffer, enlarge the existing one */ |       /* we have a buffer, enlarge the existing one */ | ||||||
|       new_rb = (char *)realloc(in->buffer, new_size); |       new_rb = (char *)realloc(in->buffer, new_size); | ||||||
| @@ -1188,7 +1217,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
| { | { | ||||||
|   int subversion=0; |   int subversion=0; | ||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
|   struct Curl_transfer_keeper *k = &data->reqdata.keep; |   struct SingleRequest *k = &data->req; | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|   int res; |   int res; | ||||||
|   long timeout = |   long timeout = | ||||||
| @@ -1214,12 +1243,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|       infof(data, "Establish HTTP proxy tunnel to %s:%d\n", |       infof(data, "Establish HTTP proxy tunnel to %s:%d\n", | ||||||
|             hostname, remote_port); |             hostname, remote_port); | ||||||
|  |  | ||||||
|       if(data->reqdata.newurl) { |       if(data->req.newurl) { | ||||||
|         /* This only happens if we've looped here due to authentication |         /* This only happens if we've looped here due to authentication | ||||||
|            reasons, and we don't really use the newly cloned URL here |            reasons, and we don't really use the newly cloned URL here | ||||||
|            then. Just free() it. */ |            then. Just free() it. */ | ||||||
|         free(data->reqdata.newurl); |         free(data->req.newurl); | ||||||
|         data->reqdata.newurl = NULL; |         data->req.newurl = NULL; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       /* initialize a dynamic send-buffer */ |       /* initialize a dynamic send-buffer */ | ||||||
| @@ -1235,7 +1264,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       /* Setup the proxy-authorization header, if any */ |       /* Setup the proxy-authorization header, if any */ | ||||||
|       result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); |       result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE); | ||||||
|  |  | ||||||
|       if(CURLE_OK == result) { |       if(CURLE_OK == result) { | ||||||
|         char *host=(char *)""; |         char *host=(char *)""; | ||||||
| @@ -1380,9 +1409,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|             keepon = FALSE; |             keepon = FALSE; | ||||||
|           else if(gotbytes <= 0) { |           else if(gotbytes <= 0) { | ||||||
|             keepon = FALSE; |             keepon = FALSE; | ||||||
|  |             if(data->set.proxyauth && data->state.authproxy.avail) { | ||||||
|  |               /* proxy auth was requested and there was proxy auth available, | ||||||
|  |                  then deem this as "mere" proxy disconnect */ | ||||||
|  |               conn->bits.proxy_connect_closed = TRUE; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|               error = SELECT_ERROR; |               error = SELECT_ERROR; | ||||||
|               failf(data, "Proxy CONNECT aborted"); |               failf(data, "Proxy CONNECT aborted"); | ||||||
|             } |             } | ||||||
|  |           } | ||||||
|           else { |           else { | ||||||
|             /* |             /* | ||||||
|              * We got a whole chunk of data, which can be anything from one |              * We got a whole chunk of data, which can be anything from one | ||||||
| @@ -1561,6 +1597,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } /* switch */ |         } /* switch */ | ||||||
|  |         if(Curl_pgrsUpdate(conn)) | ||||||
|  |           return CURLE_ABORTED_BY_CALLBACK; | ||||||
|       } /* while there's buffer left and loop is requested */ |       } /* while there's buffer left and loop is requested */ | ||||||
|  |  | ||||||
|       if(error) |       if(error) | ||||||
| @@ -1571,20 +1609,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|            headers. 'newurl' is set to a new URL if we must loop. */ |            headers. 'newurl' is set to a new URL if we must loop. */ | ||||||
|         Curl_http_auth_act(conn); |         Curl_http_auth_act(conn); | ||||||
|  |  | ||||||
|       if (closeConnection && data->reqdata.newurl) { |       if(closeConnection && data->req.newurl) { | ||||||
|         /* Connection closed by server. Don't use it anymore */ |         /* Connection closed by server. Don't use it anymore */ | ||||||
|         sclose(conn->sock[sockindex]); |         sclose(conn->sock[sockindex]); | ||||||
|         conn->sock[sockindex] = CURL_SOCKET_BAD; |         conn->sock[sockindex] = CURL_SOCKET_BAD; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|     } /* END NEGOTIATION PHASE */ |     } /* END NEGOTIATION PHASE */ | ||||||
|   } while(data->reqdata.newurl); |   } while(data->req.newurl); | ||||||
|  |  | ||||||
|   if(200 != k->httpcode) { |   if(200 != data->req.httpcode) { | ||||||
|     failf(data, "Received HTTP code %d from proxy after CONNECT", |     failf(data, "Received HTTP code %d from proxy after CONNECT", | ||||||
|           k->httpcode); |           data->req.httpcode); | ||||||
|  |  | ||||||
|     if (closeConnection && data->reqdata.newurl) |     if(closeConnection && data->req.newurl) | ||||||
|       conn->bits.proxy_connect_closed = TRUE; |       conn->bits.proxy_connect_closed = TRUE; | ||||||
|  |  | ||||||
|     return CURLE_RECV_ERROR; |     return CURLE_RECV_ERROR; | ||||||
| @@ -1599,7 +1637,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, | |||||||
|   data->state.authproxy.done = TRUE; |   data->state.authproxy.done = TRUE; | ||||||
|  |  | ||||||
|   infof (data, "Proxy replied OK to CONNECT request\n"); |   infof (data, "Proxy replied OK to CONNECT request\n"); | ||||||
|   k->ignorebody = FALSE; /* put it (back) to non-ignore state */ |   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1653,7 +1691,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) | |||||||
|   if(conn->protocol & PROT_HTTPS) { |   if(conn->protocol & PROT_HTTPS) { | ||||||
|     /* perform SSL initialization */ |     /* perform SSL initialization */ | ||||||
|     if(data->state.used_interface == Curl_if_multi) { |     if(data->state.used_interface == Curl_if_multi) { | ||||||
|       result = Curl_https_connecting(conn, done); |       result = https_connecting(conn, done); | ||||||
|       if(result) |       if(result) | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| @@ -1672,7 +1710,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) | |||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) | static CURLcode https_connecting(struct connectdata *conn, bool *done) | ||||||
| { | { | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|   DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); |   DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS)); | ||||||
| @@ -1688,7 +1726,7 @@ static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done) | |||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
| /* This function is OpenSSL-specific. It should be made to query the generic | /* This function is OpenSSL-specific. It should be made to query the generic | ||||||
|    SSL layer instead. */ |    SSL layer instead. */ | ||||||
| static int Curl_https_getsock(struct connectdata *conn, | static int https_getsock(struct connectdata *conn, | ||||||
|                               curl_socket_t *socks, |                               curl_socket_t *socks, | ||||||
|                               int numsocks) |                               int numsocks) | ||||||
| { | { | ||||||
| @@ -1713,7 +1751,7 @@ static int Curl_https_getsock(struct connectdata *conn, | |||||||
| } | } | ||||||
| #else | #else | ||||||
| #ifdef USE_GNUTLS | #ifdef USE_GNUTLS | ||||||
| int Curl_https_getsock(struct connectdata *conn, | int https_getsock(struct connectdata *conn, | ||||||
|                        curl_socket_t *socks, |                        curl_socket_t *socks, | ||||||
|                        int numsocks) |                        int numsocks) | ||||||
| { | { | ||||||
| @@ -1724,7 +1762,7 @@ int Curl_https_getsock(struct connectdata *conn, | |||||||
| } | } | ||||||
| #else | #else | ||||||
| #ifdef USE_NSS | #ifdef USE_NSS | ||||||
| int Curl_https_getsock(struct connectdata *conn, | int https_getsock(struct connectdata *conn, | ||||||
|                        curl_socket_t *socks, |                        curl_socket_t *socks, | ||||||
|                        int numsocks) |                        int numsocks) | ||||||
| { | { | ||||||
| @@ -1735,7 +1773,7 @@ int Curl_https_getsock(struct connectdata *conn, | |||||||
| } | } | ||||||
| #else | #else | ||||||
| #ifdef USE_QSOSSL | #ifdef USE_QSOSSL | ||||||
| int Curl_https_getsock(struct connectdata *conn, | int https_getsock(struct connectdata *conn, | ||||||
|                        curl_socket_t *socks, |                        curl_socket_t *socks, | ||||||
|                        int numsocks) |                        int numsocks) | ||||||
| { | { | ||||||
| @@ -1758,13 +1796,14 @@ 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->reqdata.proto.http; |   struct HTTP *http =data->state.proto.http; | ||||||
|   struct Curl_transfer_keeper *k = &data->reqdata.keep; |  | ||||||
|   (void)premature; /* not used */ |   (void)premature; /* not used */ | ||||||
|  |  | ||||||
|   /* set the proper values (possibly modified on POST) */ |   /* set the proper values (possibly modified on POST) */ | ||||||
|   conn->fread_func = data->set.fread_func; /* restore */ |   conn->fread_func = data->set.fread_func; /* restore */ | ||||||
|   conn->fread_in = data->set.in; /* restore */ |   conn->fread_in = data->set.in; /* restore */ | ||||||
|  |   conn->seek_func = data->set.seek_func; /* restore */ | ||||||
|  |   conn->seek_client = data->set.seek_client; /* restore */ | ||||||
|  |  | ||||||
|   if(http == NULL) |   if(http == NULL) | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
| @@ -1778,7 +1817,7 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(HTTPREQ_POST_FORM == data->set.httpreq) { |   if(HTTPREQ_POST_FORM == data->set.httpreq) { | ||||||
|     k->bytecount = http->readbytecount + http->writebytecount; |     data->req.bytecount = http->readbytecount + http->writebytecount; | ||||||
|  |  | ||||||
|     Curl_formclean(&http->sendit); /* Now free that whole lot */ |     Curl_formclean(&http->sendit); /* Now free that whole lot */ | ||||||
|     if(http->form.fp) { |     if(http->form.fp) { | ||||||
| @@ -1788,15 +1827,15 @@ CURLcode Curl_http_done(struct connectdata *conn, | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else if(HTTPREQ_PUT == data->set.httpreq) |   else if(HTTPREQ_PUT == data->set.httpreq) | ||||||
|     k->bytecount = http->readbytecount + http->writebytecount; |     data->req.bytecount = http->readbytecount + http->writebytecount; | ||||||
|  |  | ||||||
|   if(status != CURLE_OK) |   if(status != CURLE_OK) | ||||||
|     return (status); |     return (status); | ||||||
|  |  | ||||||
|   if(!conn->bits.retry && |   if(!conn->bits.retry && | ||||||
|      ((http->readbytecount + |      ((http->readbytecount + | ||||||
|        data->reqdata.keep.headerbytecount - |        data->req.headerbytecount - | ||||||
|        data->reqdata.keep.deductheadercount)) <= 0) { |        data->req.deductheadercount)) <= 0) { | ||||||
|     /* If this connection isn't simply closed to be retried, AND nothing was |     /* If this connection isn't simply closed to be retried, AND nothing was | ||||||
|        read from the HTTP server (that counts), this can't be right so we |        read from the HTTP server (that counts), this can't be right so we | ||||||
|        return an error here */ |        return an error here */ | ||||||
| @@ -1879,7 +1918,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|   char *buf = data->state.buffer; /* this is a short cut to the buffer */ |   char *buf = data->state.buffer; /* this is a short cut to the buffer */ | ||||||
|   CURLcode result=CURLE_OK; |   CURLcode result=CURLE_OK; | ||||||
|   struct HTTP *http; |   struct HTTP *http; | ||||||
|   char *ppath = data->reqdata.path; |   char *ppath = data->state.path; | ||||||
|   char ftp_typecode[sizeof(";type=?")] = ""; |   char ftp_typecode[sizeof(";type=?")] = ""; | ||||||
|   char *host = conn->host.name; |   char *host = conn->host.name; | ||||||
|   const char *te = ""; /* transfer-encoding */ |   const char *te = ""; /* transfer-encoding */ | ||||||
| @@ -1898,16 +1937,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|      sessionhandle, deal with it */ |      sessionhandle, deal with it */ | ||||||
|   Curl_reset_reqproto(conn); |   Curl_reset_reqproto(conn); | ||||||
|  |  | ||||||
|   if(!data->reqdata.proto.http) { |   if(!data->state.proto.http) { | ||||||
|     /* Only allocate this struct if we don't already have it! */ |     /* Only allocate this struct if we don't already have it! */ | ||||||
|  |  | ||||||
|     http = (struct HTTP *)calloc(sizeof(struct HTTP), 1); |     http = (struct HTTP *)calloc(sizeof(struct HTTP), 1); | ||||||
|     if(!http) |     if(!http) | ||||||
|       return CURLE_OUT_OF_MEMORY; |       return CURLE_OUT_OF_MEMORY; | ||||||
|     data->reqdata.proto.http = http; |     data->state.proto.http = http; | ||||||
|   } |   } | ||||||
|   else |   else | ||||||
|     http = data->reqdata.proto.http; |     http = data->state.proto.http; | ||||||
|  |  | ||||||
|   if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && |   if( (conn->protocol&(PROT_HTTP|PROT_FTP)) && | ||||||
|        data->set.upload) { |        data->set.upload) { | ||||||
| @@ -1951,7 +1990,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* setup the authentication headers */ |   /* setup the authentication headers */ | ||||||
|   result = Curl_http_output_auth(conn, request, ppath, FALSE); |   result = http_output_auth(conn, request, ppath, FALSE); | ||||||
|   if(result) |   if(result) | ||||||
|     return result; |     return result; | ||||||
|  |  | ||||||
| @@ -2035,7 +2074,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|  |  | ||||||
|     if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || |     if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || | ||||||
|        (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) |        (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) | ||||||
|       /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include |       /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include | ||||||
|          the port number in the host string */ |          the port number in the host string */ | ||||||
|       conn->allocptr.host = aprintf("Host: %s%s%s\r\n", |       conn->allocptr.host = aprintf("Host: %s%s%s\r\n", | ||||||
|                                     conn->bits.ipv6_ip?"[":"", |                                     conn->bits.ipv6_ip?"[":"", | ||||||
| @@ -2094,6 +2133,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     ppath = data->change.url; |     ppath = data->change.url; | ||||||
|  |     if (data->set.proxy_transfer_mode) { | ||||||
|       /* when doing ftp, append ;type=<a|i> if not present */ |       /* when doing ftp, append ;type=<a|i> if not present */ | ||||||
|       if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { |       if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) { | ||||||
|         char *p = strstr(ppath, ";type="); |         char *p = strstr(ppath, ";type="); | ||||||
| @@ -2112,6 +2152,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|                    data->set.prefer_ascii ? 'a' : 'i'); |                    data->set.prefer_ascii ? 'a' : 'i'); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|   if(HTTPREQ_POST_FORM == httpreq) { |   if(HTTPREQ_POST_FORM == httpreq) { | ||||||
|     /* we must build the whole darned post sequence first, so that we have |     /* we must build the whole darned post sequence first, so that we have | ||||||
|        a size of the whole shebang before we start to send it */ |        a size of the whole shebang before we start to send it */ | ||||||
| @@ -2137,7 +2178,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|   if(( (HTTPREQ_POST == httpreq) || |   if(( (HTTPREQ_POST == httpreq) || | ||||||
|        (HTTPREQ_POST_FORM == httpreq) || |        (HTTPREQ_POST_FORM == httpreq) || | ||||||
|        (HTTPREQ_PUT == httpreq) ) && |        (HTTPREQ_PUT == httpreq) ) && | ||||||
|      data->reqdata.resume_from) { |      data->state.resume_from) { | ||||||
|     /********************************************************************** |     /********************************************************************** | ||||||
|      * Resuming upload in HTTP means that we PUT or POST and that we have |      * Resuming upload in HTTP means that we PUT or POST and that we have | ||||||
|      * got a resume_from value set. The resume value has already created |      * got a resume_from value set. The resume value has already created | ||||||
| @@ -2146,30 +2187,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|      * file size before we continue this venture in the dark lands of HTTP. |      * file size before we continue this venture in the dark lands of HTTP. | ||||||
|      *********************************************************************/ |      *********************************************************************/ | ||||||
|  |  | ||||||
|     if(data->reqdata.resume_from < 0 ) { |     if(data->state.resume_from < 0 ) { | ||||||
|       /* |       /* | ||||||
|        * This is meant to get the size of the present remote-file by itself. |        * This is meant to get the size of the present remote-file by itself. | ||||||
|        * We don't support this now. Bail out! |        * We don't support this now. Bail out! | ||||||
|        */ |        */ | ||||||
|        data->reqdata.resume_from = 0; |        data->state.resume_from = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(data->reqdata.resume_from && !data->state.this_is_a_follow) { |     if(data->state.resume_from && !data->state.this_is_a_follow) { | ||||||
|       /* do we still game? */ |       /* do we still game? */ | ||||||
|       curl_off_t passed=0; |  | ||||||
|  |  | ||||||
|       /* Now, let's read off the proper amount of bytes from the |       /* Now, let's read off the proper amount of bytes from the | ||||||
|          input. If we knew it was a proper file we could've just |          input. */ | ||||||
|          fseek()ed but we only have a stream here */ |       if(conn->seek_func) { | ||||||
|  |         curl_off_t readthisamountnow = data->state.resume_from; | ||||||
|  |  | ||||||
|  |         if(conn->seek_func(conn->seek_client, | ||||||
|  | 			   readthisamountnow, SEEK_SET) != 0) { | ||||||
|  |           failf(data, "Could not seek stream"); | ||||||
|  |           return CURLE_READ_ERROR; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  | 	curl_off_t passed=0; | ||||||
|  |  | ||||||
|         do { |         do { | ||||||
|         size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed); | 	  size_t readthisamountnow = (size_t)(data->state.resume_from - passed); | ||||||
|           size_t actuallyread; |           size_t actuallyread; | ||||||
|  |  | ||||||
|           if(readthisamountnow > BUFSIZE) |           if(readthisamountnow > BUFSIZE) | ||||||
|             readthisamountnow = BUFSIZE; |             readthisamountnow = BUFSIZE; | ||||||
|  |  | ||||||
|         actuallyread = |           actuallyread = data->set.fread_func(data->state.buffer, 1, | ||||||
|           data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow, |                                               (size_t)readthisamountnow, | ||||||
|                                               data->set.in); |                                               data->set.in); | ||||||
|  |  | ||||||
|           passed += actuallyread; |           passed += actuallyread; | ||||||
| @@ -2179,11 +2230,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|                   passed); |                   passed); | ||||||
|             return CURLE_READ_ERROR; |             return CURLE_READ_ERROR; | ||||||
|           } |           } | ||||||
|       } while(passed != data->reqdata.resume_from); /* loop until done */ |         } while(passed != data->state.resume_from); /* loop until done */ | ||||||
|  |       } | ||||||
|  |  | ||||||
|       /* now, decrease the size of the read */ |       /* now, decrease the size of the read */ | ||||||
|       if(data->set.infilesize>0) { |       if(data->set.infilesize>0) { | ||||||
|         data->set.infilesize -= data->reqdata.resume_from; |         data->set.infilesize -= data->state.resume_from; | ||||||
|  |  | ||||||
|         if(data->set.infilesize <= 0) { |         if(data->set.infilesize <= 0) { | ||||||
|           failf(data, "File already completely uploaded"); |           failf(data, "File already completely uploaded"); | ||||||
| @@ -2193,7 +2245,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       /* we've passed, proceed as normal */ |       /* we've passed, proceed as normal */ | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if(data->reqdata.use_range) { |   if(data->state.use_range) { | ||||||
|     /* |     /* | ||||||
|      * A range is selected. We use different headers whether we're downloading |      * A range is selected. We use different headers whether we're downloading | ||||||
|      * or uploading and we always let customized headers override our internal |      * or uploading and we always let customized headers override our internal | ||||||
| @@ -2205,7 +2257,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       if(conn->allocptr.rangeline) |       if(conn->allocptr.rangeline) | ||||||
|         free(conn->allocptr.rangeline); |         free(conn->allocptr.rangeline); | ||||||
|       conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", |       conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", | ||||||
|                                          data->reqdata.range); |                                          data->state.range); | ||||||
|     } |     } | ||||||
|     else if((httpreq != HTTPREQ_GET) && |     else if((httpreq != HTTPREQ_GET) && | ||||||
|             !checkheaders(data, "Content-Range:")) { |             !checkheaders(data, "Content-Range:")) { | ||||||
| @@ -2214,14 +2266,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       if(conn->allocptr.rangeline) |       if(conn->allocptr.rangeline) | ||||||
|         free(conn->allocptr.rangeline); |         free(conn->allocptr.rangeline); | ||||||
|  |  | ||||||
|       if(data->reqdata.resume_from) { |       if(data->state.resume_from) { | ||||||
|         /* This is because "resume" was selected */ |         /* This is because "resume" was selected */ | ||||||
|         curl_off_t total_expected_size= |         curl_off_t total_expected_size= | ||||||
|           data->reqdata.resume_from + data->set.infilesize; |           data->state.resume_from + data->set.infilesize; | ||||||
|         conn->allocptr.rangeline = |         conn->allocptr.rangeline = | ||||||
|             aprintf("Content-Range: bytes %s%" FORMAT_OFF_T |             aprintf("Content-Range: bytes %s%" FORMAT_OFF_T | ||||||
|                     "/%" FORMAT_OFF_T "\r\n", |                     "/%" FORMAT_OFF_T "\r\n", | ||||||
|                     data->reqdata.range, total_expected_size-1, |                     data->state.range, total_expected_size-1, | ||||||
|                     total_expected_size); |                     total_expected_size); | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
| @@ -2229,7 +2281,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|            append total size */ |            append total size */ | ||||||
|         conn->allocptr.rangeline = |         conn->allocptr.rangeline = | ||||||
|             aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", |             aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", | ||||||
|                     data->reqdata.range, data->set.infilesize); |                     data->state.range, data->set.infilesize); | ||||||
|       } |       } | ||||||
|       if(!conn->allocptr.rangeline) |       if(!conn->allocptr.rangeline) | ||||||
|         return CURLE_OUT_OF_MEMORY; |         return CURLE_OUT_OF_MEMORY; | ||||||
| @@ -2274,7 +2326,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|                 conn->allocptr.proxyuserpwd? |                 conn->allocptr.proxyuserpwd? | ||||||
|                 conn->allocptr.proxyuserpwd:"", |                 conn->allocptr.proxyuserpwd:"", | ||||||
|                 conn->allocptr.userpwd?conn->allocptr.userpwd:"", |                 conn->allocptr.userpwd?conn->allocptr.userpwd:"", | ||||||
|                 (data->reqdata.use_range && conn->allocptr.rangeline)? |                 (data->state.use_range && conn->allocptr.rangeline)? | ||||||
|                 conn->allocptr.rangeline:"", |                 conn->allocptr.rangeline:"", | ||||||
|                 (data->set.str[STRING_USERAGENT] && |                 (data->set.str[STRING_USERAGENT] && | ||||||
|                  *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? |                  *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? | ||||||
| @@ -2307,7 +2359,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|         Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); |         Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); | ||||||
|         co = Curl_cookie_getlist(data->cookies, |         co = Curl_cookie_getlist(data->cookies, | ||||||
|                                  conn->allocptr.cookiehost? |                                  conn->allocptr.cookiehost? | ||||||
|                                  conn->allocptr.cookiehost:host, data->reqdata.path, |                                  conn->allocptr.cookiehost:host, | ||||||
|  |                                  data->state.path, | ||||||
|                                  (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); |                                  (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE)); | ||||||
|         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); |         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); | ||||||
|       } |       } | ||||||
| @@ -2330,7 +2383,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|           } |           } | ||||||
|           co = co->next; /* next cookie please */ |           co = co->next; /* next cookie please */ | ||||||
|         } |         } | ||||||
|         Curl_cookie_freelist(store); /* free the cookie list */ |         Curl_cookie_freelist(store, FALSE); /* free the cookie list */ | ||||||
|       } |       } | ||||||
|       if(addcookies && (CURLE_OK == result)) { |       if(addcookies && (CURLE_OK == result)) { | ||||||
|         if(!count) |         if(!count) | ||||||
| @@ -2582,10 +2635,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|           return result; |           return result; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(data->set.postfields) { |       /* For really small posts we don't use Expect: headers at all, and for | ||||||
|  |          the somewhat bigger ones we allow the app to disable it. Just make | ||||||
|         /* for really small posts we don't use Expect: headers at all, and for |          sure that the expect100header is always set to the preferred value | ||||||
|            the somewhat bigger ones we allow the app to disable it */ |          here. */ | ||||||
|       if(postsize > TINY_INITIAL_POST_SIZE) { |       if(postsize > TINY_INITIAL_POST_SIZE) { | ||||||
|         result = expect100(data, req_buffer); |         result = expect100(data, req_buffer); | ||||||
|         if(result) |         if(result) | ||||||
| @@ -2594,6 +2647,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|       else |       else | ||||||
|         data->state.expect100header = FALSE; |         data->state.expect100header = FALSE; | ||||||
|  |  | ||||||
|  |       if(data->set.postfields) { | ||||||
|  |  | ||||||
|         if(!data->state.expect100header && |         if(!data->state.expect100header && | ||||||
|            (postsize < MAX_INITIAL_POST_SIZE))  { |            (postsize < MAX_INITIAL_POST_SIZE))  { | ||||||
|           /* if we don't use expect: 100  AND |           /* if we don't use expect: 100  AND | ||||||
| @@ -2656,9 +2711,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) | |||||||
|           /* set the upload size to the progress meter */ |           /* set the upload size to the progress meter */ | ||||||
|           Curl_pgrsSetUploadSize(data, postsize?postsize:-1); |           Curl_pgrsSetUploadSize(data, postsize?postsize:-1); | ||||||
|  |  | ||||||
|           /* set the pointer to mark that we will send the post body using |           /* set the pointer to mark that we will send the post body using the | ||||||
|              the read callback */ |              read callback, but only if we're not in authenticate | ||||||
|  |              negotiation  */ | ||||||
|  |           if(!conn->bits.authneg) { | ||||||
|             http->postdata = (char *)&http->postdata; |             http->postdata = (char *)&http->postdata; | ||||||
|  |             http->postsize = postsize; | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       /* issue the request */ |       /* issue the request */ | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -109,7 +109,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|   CURLcode result=CURLE_OK; |   CURLcode result=CURLE_OK; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   struct Curl_chunker *ch = &conn->chunk; |   struct Curl_chunker *ch = &conn->chunk; | ||||||
|   struct Curl_transfer_keeper *k = &data->reqdata.keep; |   struct SingleRequest *k = &data->req; | ||||||
|   size_t piece; |   size_t piece; | ||||||
|   size_t length = (size_t)datalen; |   size_t length = (size_t)datalen; | ||||||
|   size_t *wrote = (size_t *)wrotep; |   size_t *wrote = (size_t *)wrotep; | ||||||
| @@ -118,8 +118,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|  |  | ||||||
|   /* the original data is written to the client, but we go on with the |   /* the original data is written to the client, but we go on with the | ||||||
|      chunk read process, to properly calculate the content length*/ |      chunk read process, to properly calculate the content length*/ | ||||||
|   if (data->set.http_te_skip && !k->ignorebody) |   if(data->set.http_te_skip && !k->ignorebody) { | ||||||
|     Curl_client_write(conn, CLIENTWRITE_BODY, datap,datalen); |     result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); | ||||||
|  |     if(result) | ||||||
|  |       return CHUNKE_WRITE_ERROR; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   while(length) { |   while(length) { | ||||||
|     switch(ch->state) { |     switch(ch->state) { | ||||||
| @@ -178,7 +181,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|       if(*datap == 0x0a) { |       if(*datap == 0x0a) { | ||||||
|         /* we're now expecting data to come, unless size was zero! */ |         /* we're now expecting data to come, unless size was zero! */ | ||||||
|         if(0 == ch->datasize) { |         if(0 == ch->datasize) { | ||||||
|           if (conn->bits.trailerHdrPresent!=TRUE) { |           if(conn->bits.trailerhdrpresent!=TRUE) { | ||||||
|             /* No Trailer: header found - revert to original Curl processing */ |             /* No Trailer: header found - revert to original Curl processing */ | ||||||
|             ch->state = CHUNK_STOPCR; |             ch->state = CHUNK_STOPCR; | ||||||
|  |  | ||||||
| @@ -217,7 +220,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|       /* Write the data portion available */ |       /* Write the data portion available */ | ||||||
| #ifdef HAVE_LIBZ | #ifdef HAVE_LIBZ | ||||||
|       switch (conn->data->set.http_ce_skip? |       switch (conn->data->set.http_ce_skip? | ||||||
|               IDENTITY : data->reqdata.keep.content_encoding) { |               IDENTITY : data->req.content_encoding) { | ||||||
|       case IDENTITY: |       case IDENTITY: | ||||||
| #endif | #endif | ||||||
|         if(!k->ignorebody) { |         if(!k->ignorebody) { | ||||||
| @@ -231,16 +234,16 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case DEFLATE: |       case DEFLATE: | ||||||
|         /* update data->reqdata.keep.str to point to the chunk data. */ |         /* update data->req.keep.str to point to the chunk data. */ | ||||||
|         data->reqdata.keep.str = datap; |         data->req.str = datap; | ||||||
|         result = Curl_unencode_deflate_write(conn, &data->reqdata.keep, |         result = Curl_unencode_deflate_write(conn, &data->req, | ||||||
|                                              (ssize_t)piece); |                                              (ssize_t)piece); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       case GZIP: |       case GZIP: | ||||||
|         /* update data->reqdata.keep.str to point to the chunk data. */ |         /* update data->req.keep.str to point to the chunk data. */ | ||||||
|         data->reqdata.keep.str = datap; |         data->req.str = datap; | ||||||
|         result = Curl_unencode_gzip_write(conn, &data->reqdata.keep, |         result = Curl_unencode_gzip_write(conn, &data->req, | ||||||
|                                           (ssize_t)piece); |                                           (ssize_t)piece); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
| @@ -362,9 +365,12 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, | |||||||
|             return(CHUNKE_BAD_CHUNK); |             return(CHUNKE_BAD_CHUNK); | ||||||
|           } |           } | ||||||
| #endif /* CURL_DOES_CONVERSIONS */ | #endif /* CURL_DOES_CONVERSIONS */ | ||||||
|           if ( !data->set.http_te_skip ) |           if(!data->set.http_te_skip) { | ||||||
|             Curl_client_write(conn, CLIENTWRITE_HEADER, |             result = Curl_client_write(conn, CLIENTWRITE_HEADER, | ||||||
|                                        conn->trailer, conn->trlPos); |                                        conn->trailer, conn->trlPos); | ||||||
|  |             if(result) | ||||||
|  |               return CHUNKE_WRITE_ERROR; | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|         ch->state = CHUNK_TRAILER; |         ch->state = CHUNK_TRAILER; | ||||||
|         conn->trlPos=0; |         conn->trlPos=0; | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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,19 +90,19 @@ CURLdigest Curl_input_digest(struct connectdata *conn, | |||||||
|     Curl_digest_cleanup_one(d); |     Curl_digest_cleanup_one(d); | ||||||
|  |  | ||||||
|     while(more) { |     while(more) { | ||||||
|       char value[32]; |       char value[256]; | ||||||
|       char content[128]; |       char content[1024]; | ||||||
|       size_t totlen=0; |       size_t totlen=0; | ||||||
|  |  | ||||||
|       while(*header && ISSPACE(*header)) |       while(*header && ISSPACE(*header)) | ||||||
|         header++; |         header++; | ||||||
|  |  | ||||||
|       /* how big can these strings be? */ |       /* how big can these strings be? */ | ||||||
|       if((2 == sscanf(header, "%31[^=]=\"%127[^\"]\"", |       if((2 == sscanf(header, "%255[^=]=\"%1023[^\"]\"", | ||||||
|                       value, content)) || |                       value, content)) || | ||||||
|          /* try the same scan but without quotes around the content but don't |          /* try the same scan but without quotes around the content but don't | ||||||
|             include the possibly trailing comma, newline or carriage return */ |             include the possibly trailing comma, newline or carriage return */ | ||||||
|          (2 ==  sscanf(header, "%31[^=]=%127[^\r\n,]", |          (2 ==  sscanf(header, "%255[^=]=%1023[^\r\n,]", | ||||||
|                        value, content)) ) { |                        value, content)) ) { | ||||||
|         if(strequal(value, "nonce")) { |         if(strequal(value, "nonce")) { | ||||||
|           d->nonce = strdup(content); |           d->nonce = strdup(content); | ||||||
| @@ -180,6 +180,9 @@ CURLdigest Curl_input_digest(struct connectdata *conn, | |||||||
|         break; /* we're done here */ |         break; /* we're done here */ | ||||||
|  |  | ||||||
|       header += totlen; |       header += totlen; | ||||||
|  |       /* pass all additional spaces here */ | ||||||
|  |       while(*header && ISSPACE(*header)) | ||||||
|  |         header++; | ||||||
|       if(',' == *header) |       if(',' == *header) | ||||||
|         /* allow the list to be comma-separated */ |         /* allow the list to be comma-separated */ | ||||||
|         header++; |         header++; | ||||||
|   | |||||||
| @@ -51,7 +51,8 @@ | |||||||
| static int | static int | ||||||
| get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server) | get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server) | ||||||
| { | { | ||||||
|   struct negotiatedata *neg_ctx = &conn->data->state.negotiate; |   struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: | ||||||
|  |     &conn->data->state.negotiate; | ||||||
|   OM_uint32 major_status, minor_status; |   OM_uint32 major_status, minor_status; | ||||||
|   gss_buffer_desc token = GSS_C_EMPTY_BUFFER; |   gss_buffer_desc token = GSS_C_EMPTY_BUFFER; | ||||||
|   char name[2048]; |   char name[2048]; | ||||||
| @@ -69,11 +70,13 @@ get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server) | |||||||
|   else |   else | ||||||
|     service = "HTTP"; |     service = "HTTP"; | ||||||
|  |  | ||||||
|   token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : conn->host.name) + 1; |   token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : | ||||||
|  |                                               conn->host.name) + 1; | ||||||
|   if(token.length + 1 > sizeof(name)) |   if(token.length + 1 > sizeof(name)) | ||||||
|     return EMSGSIZE; |     return EMSGSIZE; | ||||||
|  |  | ||||||
|   snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : conn->host.name); |   snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : | ||||||
|  |            conn->host.name); | ||||||
|  |  | ||||||
|   token.value = (void *) name; |   token.value = (void *) name; | ||||||
|   major_status = gss_import_name(&minor_status, |   major_status = gss_import_name(&minor_status, | ||||||
| @@ -113,9 +116,11 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix) | |||||||
|   infof(conn->data, "%s", buf); |   infof(conn->data, "%s", buf); | ||||||
| } | } | ||||||
|  |  | ||||||
| int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header) | int Curl_input_negotiate(struct connectdata *conn, bool proxy, | ||||||
|  |                          const char *header) | ||||||
| { | { | ||||||
|   struct negotiatedata *neg_ctx = &conn->data->state.negotiate; |   struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: | ||||||
|  |     &conn->data->state.negotiate; | ||||||
|   OM_uint32 major_status, minor_status, minor_status2; |   OM_uint32 major_status, minor_status, minor_status2; | ||||||
|   gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; |   gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | ||||||
|   gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; |   gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | ||||||
| @@ -165,7 +170,8 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *heade | |||||||
|  |  | ||||||
|   len = strlen(header); |   len = strlen(header); | ||||||
|   if(len > 0) { |   if(len > 0) { | ||||||
|     int rawlen = Curl_base64_decode(header, (unsigned char **)&input_token.value); |     int rawlen = Curl_base64_decode(header, | ||||||
|  |                                     (unsigned char **)&input_token.value); | ||||||
|     if(rawlen < 0) |     if(rawlen < 0) | ||||||
|       return -1; |       return -1; | ||||||
|     input_token.length = rawlen; |     input_token.length = rawlen; | ||||||
| @@ -247,7 +253,8 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *heade | |||||||
|  |  | ||||||
| CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) | CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) | ||||||
| { | { | ||||||
|   struct negotiatedata *neg_ctx = &conn->data->state.negotiate; |   struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: | ||||||
|  |     &conn->data->state.negotiate; | ||||||
|   OM_uint32 minor_status; |   OM_uint32 minor_status; | ||||||
|   char *encoded = NULL; |   char *encoded = NULL; | ||||||
|   int len; |   int len; | ||||||
| @@ -299,17 +306,16 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) | |||||||
|     return CURLE_OUT_OF_MEMORY; |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|   conn->allocptr.userpwd = |   conn->allocptr.userpwd = | ||||||
|     aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", neg_ctx->protocol, encoded); |     aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", | ||||||
|  |             neg_ctx->protocol, encoded); | ||||||
|   free(encoded); |   free(encoded); | ||||||
|   gss_release_buffer(&minor_status, &neg_ctx->output_token); |   gss_release_buffer(&minor_status, &neg_ctx->output_token); | ||||||
|   return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; |   return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Curl_cleanup_negotiate(struct SessionHandle *data) | static void cleanup(struct negotiatedata *neg_ctx) | ||||||
| { | { | ||||||
|   OM_uint32 minor_status; |   OM_uint32 minor_status; | ||||||
|   struct negotiatedata *neg_ctx = &data->state.negotiate; |  | ||||||
|  |  | ||||||
|   if(neg_ctx->context != GSS_C_NO_CONTEXT) |   if(neg_ctx->context != GSS_C_NO_CONTEXT) | ||||||
|     gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER); |     gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER); | ||||||
|  |  | ||||||
| @@ -322,6 +328,12 @@ void Curl_cleanup_negotiate(struct SessionHandle *data) | |||||||
|   memset(neg_ctx, 0, sizeof(*neg_ctx)); |   memset(neg_ctx, 0, sizeof(*neg_ctx)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void Curl_cleanup_negotiate(struct SessionHandle *data) | ||||||
|  | { | ||||||
|  |   cleanup(&data->state.negotiate); | ||||||
|  |   cleanup(&data->state.proxyneg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -122,12 +122,14 @@ inet_pton4(const char *src, unsigned char *dst) | |||||||
|           return (0); |           return (0); | ||||||
|         saw_digit = 1; |         saw_digit = 1; | ||||||
|       } |       } | ||||||
|     } else if (ch == '.' && saw_digit) { |     } | ||||||
|  |     else if(ch == '.' && saw_digit) { | ||||||
|       if(octets == 4) |       if(octets == 4) | ||||||
|         return (0); |         return (0); | ||||||
|       *++tp = 0; |       *++tp = 0; | ||||||
|       saw_digit = 0; |       saw_digit = 0; | ||||||
|     } else |     } | ||||||
|  |     else | ||||||
|       return (0); |       return (0); | ||||||
|   } |   } | ||||||
|   if(octets < 4) |   if(octets < 4) | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  * |  * | ||||||
|  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan |  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan | ||||||
|  * (Royal Institute of Technology, Stockholm, Sweden). |  * (Royal Institute of Technology, Stockholm, Sweden). | ||||||
|  * Copyright (c) 2004 - 2007 Daniel Stenberg |  * Copyright (c) 2004 - 2008 Daniel Stenberg | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
|  * |  * | ||||||
|  * Redistribution and use in source and binary forms, with or without |  * Redistribution and use in source and binary forms, with or without | ||||||
| @@ -362,7 +362,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn) | |||||||
|     tmp=0; |     tmp=0; | ||||||
|   } |   } | ||||||
|   if(!tmp || !ptr) { |   if(!tmp || !ptr) { | ||||||
|     Curl_failf(conn->data, "Failed to decode base64 in reply.\n"); |     Curl_failf(conn->data, "Failed to decode base64 in reply"); | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     return CURLE_FTP_WEIRD_SERVER_REPLY; |     return CURLE_FTP_WEIRD_SERVER_REPLY; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -555,7 +555,7 @@ static bool unescape_elements (void *data, LDAPURLDesc *ludp) | |||||||
|  * |  * | ||||||
|  * <hostname> already known from 'conn->host.name'. |  * <hostname> already known from 'conn->host.name'. | ||||||
|  * <port>     already known from 'conn->remote_port'. |  * <port>     already known from 'conn->remote_port'. | ||||||
|  * extract the rest from 'conn->data->reqdata.path+1'. All fields are optional. |  * extract the rest from 'conn->data->state.path+1'. All fields are optional. | ||||||
|  * e.g. |  * e.g. | ||||||
|  *   ldap://<hostname>:<port>/?<attributes>?<scope>?<filter> |  *   ldap://<hostname>:<port>/?<attributes>?<scope>?<filter> | ||||||
|  * yields ludp->lud_dn = "". |  * yields ludp->lud_dn = "". | ||||||
| @@ -568,8 +568,8 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) | |||||||
|   int i; |   int i; | ||||||
|  |  | ||||||
|   if(!conn->data || |   if(!conn->data || | ||||||
|       !conn->data->reqdata.path || |       !conn->data->state.path || | ||||||
|       conn->data->reqdata.path[0] != '/' || |       conn->data->state.path[0] != '/' || | ||||||
|       !checkprefix(conn->protostr, conn->data->change.url)) |       !checkprefix(conn->protostr, conn->data->change.url)) | ||||||
|     return LDAP_INVALID_SYNTAX; |     return LDAP_INVALID_SYNTAX; | ||||||
|  |  | ||||||
| @@ -579,7 +579,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) | |||||||
|  |  | ||||||
|   /* parse DN (Distinguished Name). |   /* parse DN (Distinguished Name). | ||||||
|    */ |    */ | ||||||
|   ludp->lud_dn = strdup(conn->data->reqdata.path+1); |   ludp->lud_dn = strdup(conn->data->state.path+1); | ||||||
|   if(!ludp->lud_dn) |   if(!ludp->lud_dn) | ||||||
|     return LDAP_NO_MEMORY; |     return LDAP_NO_MEMORY; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -52,7 +52,8 @@ BEGIN | |||||||
|       VALUE "OriginalFilename", "libcurl.dll\0" |       VALUE "OriginalFilename", "libcurl.dll\0" | ||||||
|       VALUE "ProductName",      "The cURL library\0" |       VALUE "ProductName",      "The cURL library\0" | ||||||
|       VALUE "ProductVersion",   LIBCURL_VERSION "\0" |       VALUE "ProductVersion",   LIBCURL_VERSION "\0" | ||||||
|       VALUE "LegalCopyright",   "Copyright 1996-2007 by Daniel Stenberg. http://curl.haxx.se/docs/copyright.html\0" |       VALUE "LegalCopyright",   "<EFBFBD> " LIBCURL_COPYRIGHT "\0" | ||||||
|  |       VALUE "License",          "http://curl.haxx.se/docs/copyright.html\0" | ||||||
|     END |     END | ||||||
|   END |   END | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								lib/llist.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								lib/llist.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -136,3 +136,52 @@ Curl_llist_count(struct curl_llist *list) | |||||||
| { | { | ||||||
|   return list->size; |   return list->size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, | ||||||
|  |                     struct curl_llist *to_list, struct curl_llist_element *to_e) | ||||||
|  | { | ||||||
|  |   /* Remove element from list */ | ||||||
|  |   if(e == NULL || list->size == 0) | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|  |   if(e == list->head) { | ||||||
|  |     list->head = e->next; | ||||||
|  |  | ||||||
|  |     if(list->head == NULL) | ||||||
|  |       list->tail = NULL; | ||||||
|  |     else | ||||||
|  |       e->next->prev = NULL; | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     e->prev->next = e->next; | ||||||
|  |     if(!e->next) | ||||||
|  |       list->tail = e->prev; | ||||||
|  |     else | ||||||
|  |       e->next->prev = e->prev; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   --list->size; | ||||||
|  |  | ||||||
|  |   /* Add element to to_list after to_e */ | ||||||
|  |   if(to_list->size == 0) { | ||||||
|  |     to_list->head = e; | ||||||
|  |     to_list->head->prev = NULL; | ||||||
|  |     to_list->head->next = NULL; | ||||||
|  |     to_list->tail = e; | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     e->next = to_e->next; | ||||||
|  |     e->prev = to_e; | ||||||
|  |     if(to_e->next) { | ||||||
|  |       to_e->next->prev = e; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       to_list->tail = e; | ||||||
|  |     } | ||||||
|  |     to_e->next = e; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ++to_list->size; | ||||||
|  |  | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -56,5 +56,7 @@ int Curl_llist_remove_next(struct curl_llist *, struct curl_llist_element *, | |||||||
|                            void *); |                            void *); | ||||||
| size_t Curl_llist_count(struct curl_llist *); | size_t Curl_llist_count(struct curl_llist *); | ||||||
| void Curl_llist_destroy(struct curl_llist *, void *); | void Curl_llist_destroy(struct curl_llist *, void *); | ||||||
|  | int Curl_llist_move(struct curl_llist *, struct curl_llist_element *, | ||||||
|  |                     struct curl_llist *, struct curl_llist_element *); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2007, 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 | ||||||
|   | |||||||
| @@ -686,8 +686,11 @@ static int dprintf_formatf( | |||||||
|       width = p->width; |       width = p->width; | ||||||
|  |  | ||||||
|     /* pick up the specified precision */ |     /* pick up the specified precision */ | ||||||
|     if(p->flags & FLAGS_PRECPARAM) |     if(p->flags & FLAGS_PRECPARAM) { | ||||||
|       prec = vto[p->precision].data.num; |       prec = vto[p->precision].data.num; | ||||||
|  |       param_num++; /* since the precision is extraced from a parameter, we | ||||||
|  |                       must skip that to get to the next one properly */ | ||||||
|  |     } | ||||||
|     else if(p->flags & FLAGS_PREC) |     else if(p->flags & FLAGS_PREC) | ||||||
|       prec = p->precision; |       prec = p->precision; | ||||||
|     else |     else | ||||||
|   | |||||||
							
								
								
									
										202
									
								
								lib/multi.c
									
									
									
									
									
								
							
							
						
						
									
										202
									
								
								lib/multi.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -85,7 +85,6 @@ typedef enum { | |||||||
|   CURLM_STATE_TOOFAST,     /* wait because limit-rate exceeded */ |   CURLM_STATE_TOOFAST,     /* wait because limit-rate exceeded */ | ||||||
|   CURLM_STATE_DONE,        /* post data transfer operation */ |   CURLM_STATE_DONE,        /* post data transfer operation */ | ||||||
|   CURLM_STATE_COMPLETED,   /* operation complete */ |   CURLM_STATE_COMPLETED,   /* operation complete */ | ||||||
|   CURLM_STATE_CANCELLED,   /* cancelled */ |  | ||||||
|  |  | ||||||
|   CURLM_STATE_LAST /* not a true state, never use this */ |   CURLM_STATE_LAST /* not a true state, never use this */ | ||||||
| } CURLMstate; | } CURLMstate; | ||||||
| @@ -190,6 +189,14 @@ static void add_closure(struct Curl_multi *multi, | |||||||
|                         struct SessionHandle *data); |                         struct SessionHandle *data); | ||||||
| static int update_timer(struct Curl_multi *multi); | static int update_timer(struct Curl_multi *multi); | ||||||
|  |  | ||||||
|  | static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle, | ||||||
|  |                                               struct connectdata *conn); | ||||||
|  | static int checkPendPipeline(struct connectdata *conn); | ||||||
|  | static int moveHandleFromSendToRecvPipeline(struct SessionHandle *habdle, | ||||||
|  |                                             struct connectdata *conn); | ||||||
|  | static bool isHandleAtHead(struct SessionHandle *handle, | ||||||
|  |                            struct curl_llist *pipeline); | ||||||
|  |  | ||||||
| #ifdef CURLDEBUG | #ifdef CURLDEBUG | ||||||
| static const char * const statename[]={ | static const char * const statename[]={ | ||||||
|   "INIT", |   "INIT", | ||||||
| @@ -208,7 +215,6 @@ static const char * const statename[]={ | |||||||
|   "TOOFAST", |   "TOOFAST", | ||||||
|   "DONE", |   "DONE", | ||||||
|   "COMPLETED", |   "COMPLETED", | ||||||
|   "CANCELLED" |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void curl_multi_dump(CURLM *multi_handle); | void curl_multi_dump(CURLM *multi_handle); | ||||||
| @@ -578,15 +584,17 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle, | |||||||
|          alive connections when this is removed */ |          alive connections when this is removed */ | ||||||
|       multi->num_alive--; |       multi->num_alive--; | ||||||
|  |  | ||||||
|     if (easy->easy_handle->state.is_in_pipeline && |     if(easy->easy_conn && | ||||||
|         easy->state > CURLM_STATE_DO && |         easy->easy_handle->state.is_in_pipeline && | ||||||
|  |         easy->state > CURLM_STATE_WAITDO && | ||||||
|         easy->state < CURLM_STATE_COMPLETED) { |         easy->state < CURLM_STATE_COMPLETED) { | ||||||
|       /* If the handle is in a pipeline and has finished sending off its |       /* If the handle is in a pipeline and has started sending off its | ||||||
|          request but not received its reponse yet, we need to remember the |          request but not received its reponse yet, we need to close | ||||||
|          fact that we want to remove this handle but do the actual removal at |          connection. */ | ||||||
|          a later time */ |       easy->easy_conn->bits.close = TRUE; | ||||||
|       easy->easy_handle->state.cancelled = TRUE; |       /* Set connection owner so that Curl_done() closes it. | ||||||
|       return CURLM_OK; |          We can sefely do this here since connection is killed. */ | ||||||
|  |       easy->easy_conn->data = easy->easy_handle; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* The timer must be shut down before easy->multi is set to NULL, |     /* The timer must be shut down before easy->multi is set to NULL, | ||||||
| @@ -772,6 +780,7 @@ static int multi_getsock(struct Curl_one_easy *easy, | |||||||
|   case CURLM_STATE_DOING: |   case CURLM_STATE_DOING: | ||||||
|     return Curl_doing_getsock(easy->easy_conn, socks, numsocks); |     return Curl_doing_getsock(easy->easy_conn, socks, numsocks); | ||||||
|  |  | ||||||
|  |   case CURLM_STATE_WAITPROXYCONNECT: | ||||||
|   case CURLM_STATE_WAITCONNECT: |   case CURLM_STATE_WAITCONNECT: | ||||||
|     return waitconnect_getsock(easy->easy_conn, socks, numsocks); |     return waitconnect_getsock(easy->easy_conn, socks, numsocks); | ||||||
|  |  | ||||||
| @@ -845,7 +854,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|   bool dophase_done; |   bool dophase_done; | ||||||
|   bool done; |   bool done; | ||||||
|   CURLMcode result = CURLM_OK; |   CURLMcode result = CURLM_OK; | ||||||
|   struct Curl_transfer_keeper *k; |   struct SingleRequest *k; | ||||||
|  |  | ||||||
|   do { |   do { | ||||||
|     bool disconnect_conn = FALSE; |     bool disconnect_conn = FALSE; | ||||||
| @@ -857,11 +866,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|        we're using gets cleaned up and we're left with nothing. */ |        we're using gets cleaned up and we're left with nothing. */ | ||||||
|     if(easy->easy_handle->state.pipe_broke) { |     if(easy->easy_handle->state.pipe_broke) { | ||||||
|       infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n", |       infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n", | ||||||
|             easy, easy->easy_handle->reqdata.path); |             easy, easy->easy_handle->state.path); | ||||||
|  |  | ||||||
|       if(easy->easy_handle->state.is_in_pipeline) { |       if(easy->easy_handle->state.is_in_pipeline) { | ||||||
|         /* Head back to the CONNECT state */ |         /* Head back to the CONNECT state */ | ||||||
|         multistate(easy, CURLM_STATE_CONNECT); |         multistate(easy, CURLM_STATE_CONNECT); | ||||||
|  |         easy->easy_handle->state.is_in_pipeline = FALSE; | ||||||
|         result = CURLM_CALL_MULTI_PERFORM; |         result = CURLM_CALL_MULTI_PERFORM; | ||||||
|         easy->result = CURLE_OK; |         easy->result = CURLE_OK; | ||||||
|       } |       } | ||||||
| @@ -932,10 +942,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|                                   &async, &protocol_connect); |                                   &async, &protocol_connect); | ||||||
|  |  | ||||||
|       if(CURLE_OK == easy->result) { |       if(CURLE_OK == easy->result) { | ||||||
|         /* Add this handle to the send pipeline */ |         /* Add this handle to the send or pend pipeline */ | ||||||
|         easy->result = Curl_addHandleToPipeline(easy->easy_handle, |         easy->result = addHandleToSendOrPendPipeline(easy->easy_handle, | ||||||
|                                                 easy->easy_conn->send_pipe); |                                                      easy->easy_conn); | ||||||
|         if(CURLE_OK == easy->result) { |         if(CURLE_OK == easy->result) { | ||||||
|  |           if (easy->easy_handle->state.is_in_pipeline) { | ||||||
|  |             multistate(easy, CURLM_STATE_WAITDO); | ||||||
|  |             if(isHandleAtHead(easy->easy_handle, | ||||||
|  |                               easy->easy_conn->send_pipe)) | ||||||
|  |               result = CURLM_CALL_MULTI_PERFORM; | ||||||
|  |           } | ||||||
|  |           else { | ||||||
|             if(async) |             if(async) | ||||||
|               /* We're now waiting for an asynchronous name lookup */ |               /* We're now waiting for an asynchronous name lookup */ | ||||||
|               multistate(easy, CURLM_STATE_WAITRESOLVE); |               multistate(easy, CURLM_STATE_WAITRESOLVE); | ||||||
| @@ -958,6 +975,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case CURLM_STATE_WAITRESOLVE: |     case CURLM_STATE_WAITRESOLVE: | ||||||
| @@ -1057,7 +1075,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|       /* protocol-specific connect phase */ |       /* protocol-specific connect phase */ | ||||||
|       easy->result = Curl_protocol_connecting(easy->easy_conn, |       easy->result = Curl_protocol_connecting(easy->easy_conn, | ||||||
|                                               &protocol_connect); |                                               &protocol_connect); | ||||||
|       if(protocol_connect) { |       if((easy->result == CURLE_OK) && protocol_connect) { | ||||||
|         /* after the connect has completed, go WAITDO */ |         /* after the connect has completed, go WAITDO */ | ||||||
|         multistate(easy, CURLM_STATE_WAITDO); |         multistate(easy, CURLM_STATE_WAITDO); | ||||||
|         result = CURLM_CALL_MULTI_PERFORM; |         result = CURLM_CALL_MULTI_PERFORM; | ||||||
| @@ -1077,11 +1095,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|             easy->easy_conn->connectindex, |             easy->easy_conn->connectindex, | ||||||
|             easy->easy_conn->send_pipe->size, |             easy->easy_conn->send_pipe->size, | ||||||
|             easy->easy_conn->writechannel_inuse, |             easy->easy_conn->writechannel_inuse, | ||||||
|             Curl_isHandleAtHead(easy->easy_handle, |             isHandleAtHead(easy->easy_handle, | ||||||
|                            easy->easy_conn->send_pipe)); |                            easy->easy_conn->send_pipe)); | ||||||
| #endif | #endif | ||||||
|       if(!easy->easy_conn->writechannel_inuse && |       if(!easy->easy_conn->writechannel_inuse && | ||||||
|           Curl_isHandleAtHead(easy->easy_handle, |          isHandleAtHead(easy->easy_handle, | ||||||
|                         easy->easy_conn->send_pipe)) { |                         easy->easy_conn->send_pipe)) { | ||||||
|         /* Grab the channel */ |         /* Grab the channel */ | ||||||
|         easy->easy_conn->writechannel_inuse = TRUE; |         easy->easy_conn->writechannel_inuse = TRUE; | ||||||
| @@ -1121,13 +1139,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|           } |           } | ||||||
|           else { |           else { | ||||||
|             /* we're done with the DO, now DO_DONE */ |             /* we're done with the DO, now DO_DONE */ | ||||||
|             easy->result = Curl_readwrite_init(easy->easy_conn); |  | ||||||
|             if(CURLE_OK == easy->result) { |  | ||||||
|             multistate(easy, CURLM_STATE_DO_DONE); |             multistate(easy, CURLM_STATE_DO_DONE); | ||||||
|             result = CURLM_CALL_MULTI_PERFORM; |             result = CURLM_CALL_MULTI_PERFORM; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         else { |         else { | ||||||
|           /* failure detected */ |           /* failure detected */ | ||||||
|           Curl_posttransfer(easy->easy_handle); |           Curl_posttransfer(easy->easy_handle); | ||||||
| @@ -1152,12 +1167,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|           } |           } | ||||||
|           else { |           else { | ||||||
|             /* we're done with the DO, now DO_DONE */ |             /* we're done with the DO, now DO_DONE */ | ||||||
|             easy->result = Curl_readwrite_init(easy->easy_conn); |  | ||||||
|             if(CURLE_OK == easy->result) { |  | ||||||
|             multistate(easy, CURLM_STATE_DO_DONE); |             multistate(easy, CURLM_STATE_DO_DONE); | ||||||
|             result = CURLM_CALL_MULTI_PERFORM; |             result = CURLM_CALL_MULTI_PERFORM; | ||||||
|           } |           } | ||||||
|           } |  | ||||||
|         } /* dophase_done */ |         } /* dophase_done */ | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
| @@ -1179,32 +1191,29 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|          */ |          */ | ||||||
|         easy->result = Curl_do_more(easy->easy_conn); |         easy->result = Curl_do_more(easy->easy_conn); | ||||||
|  |  | ||||||
|         if(CURLE_OK == easy->result) |         /* No need to remove ourselves from the send pipeline here since that | ||||||
|           easy->result = Curl_readwrite_init(easy->easy_conn); |            is done for us in Curl_done() */ | ||||||
|         else |  | ||||||
|           /* Remove ourselves from the send pipeline */ |  | ||||||
|           Curl_removeHandleFromPipeline(easy->easy_handle, |  | ||||||
|                                         easy->easy_conn->send_pipe); |  | ||||||
|  |  | ||||||
|         if(CURLE_OK == easy->result) { |         if(CURLE_OK == easy->result) { | ||||||
|           multistate(easy, CURLM_STATE_DO_DONE); |           multistate(easy, CURLM_STATE_DO_DONE); | ||||||
|           result = CURLM_CALL_MULTI_PERFORM; |           result = CURLM_CALL_MULTI_PERFORM; | ||||||
|         } |         } | ||||||
|  |         else { | ||||||
|  |           /* failure detected */ | ||||||
|  |           Curl_posttransfer(easy->easy_handle); | ||||||
|  |           Curl_done(&easy->easy_conn, easy->result, FALSE); | ||||||
|  |           disconnect_conn = TRUE; | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case CURLM_STATE_DO_DONE: |     case CURLM_STATE_DO_DONE: | ||||||
|       /* Remove ourselves from the send pipeline */ |       /* Move ourselves from the send to recv pipeline */ | ||||||
|       Curl_removeHandleFromPipeline(easy->easy_handle, |       moveHandleFromSendToRecvPipeline(easy->easy_handle, easy->easy_conn); | ||||||
|                                     easy->easy_conn->send_pipe); |       /* Check if we can move pending requests to send pipe */ | ||||||
|       /* Add ourselves to the recv pipeline */ |       checkPendPipeline(easy->easy_conn); | ||||||
|       easy->result = Curl_addHandleToPipeline(easy->easy_handle, |  | ||||||
|                                               easy->easy_conn->recv_pipe); |  | ||||||
|       multistate(easy, CURLM_STATE_WAITPERFORM); |       multistate(easy, CURLM_STATE_WAITPERFORM); | ||||||
|       result = CURLM_CALL_MULTI_PERFORM; |       result = CURLM_CALL_MULTI_PERFORM; | ||||||
|  |  | ||||||
|       Curl_pre_readwrite(easy->easy_conn); |  | ||||||
|  |  | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case CURLM_STATE_WAITPERFORM: |     case CURLM_STATE_WAITPERFORM: | ||||||
| @@ -1213,12 +1222,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|             easy->easy_conn->connectindex, |             easy->easy_conn->connectindex, | ||||||
|             easy->easy_conn->recv_pipe->size, |             easy->easy_conn->recv_pipe->size, | ||||||
|             easy->easy_conn->readchannel_inuse, |             easy->easy_conn->readchannel_inuse, | ||||||
|             Curl_isHandleAtHead(easy->easy_handle, |             isHandleAtHead(easy->easy_handle, | ||||||
|                            easy->easy_conn->recv_pipe)); |                            easy->easy_conn->recv_pipe)); | ||||||
| #endif | #endif | ||||||
|       /* Wait for our turn to PERFORM */ |       /* Wait for our turn to PERFORM */ | ||||||
|       if(!easy->easy_conn->readchannel_inuse && |       if(!easy->easy_conn->readchannel_inuse && | ||||||
|           Curl_isHandleAtHead(easy->easy_handle, |          isHandleAtHead(easy->easy_handle, | ||||||
|                         easy->easy_conn->recv_pipe)) { |                         easy->easy_conn->recv_pipe)) { | ||||||
|         /* Grab the channel */ |         /* Grab the channel */ | ||||||
|         easy->easy_conn->readchannel_inuse = TRUE; |         easy->easy_conn->readchannel_inuse = TRUE; | ||||||
| @@ -1259,7 +1268,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|       /* read/write data if it is ready to do so */ |       /* read/write data if it is ready to do so */ | ||||||
|       easy->result = Curl_readwrite(easy->easy_conn, &done); |       easy->result = Curl_readwrite(easy->easy_conn, &done); | ||||||
|  |  | ||||||
|       k = &easy->easy_handle->reqdata.keep; |       k = &easy->easy_handle->req; | ||||||
|  |  | ||||||
|       if(!(k->keepon & KEEP_READ)) { |       if(!(k->keepon & KEEP_READ)) { | ||||||
|         /* We're done reading */ |         /* We're done reading */ | ||||||
| @@ -1278,6 +1287,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|         easy->easy_conn->bits.close = TRUE; |         easy->easy_conn->bits.close = TRUE; | ||||||
|         Curl_removeHandleFromPipeline(easy->easy_handle, |         Curl_removeHandleFromPipeline(easy->easy_handle, | ||||||
|                                       easy->easy_conn->recv_pipe); |                                       easy->easy_conn->recv_pipe); | ||||||
|  |         easy->easy_handle->state.is_in_pipeline = FALSE; | ||||||
|  |  | ||||||
|         if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) { |         if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) { | ||||||
|           /* if we failed anywhere, we must clean up the secondary socket if |           /* if we failed anywhere, we must clean up the secondary socket if | ||||||
| @@ -1296,14 +1306,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|         Curl_posttransfer(easy->easy_handle); |         Curl_posttransfer(easy->easy_handle); | ||||||
|  |  | ||||||
|         /* When we follow redirects, must to go back to the CONNECT state */ |         /* When we follow redirects, must to go back to the CONNECT state */ | ||||||
|         if(easy->easy_handle->reqdata.newurl || retry) { |         if(easy->easy_handle->req.newurl || retry) { | ||||||
|           Curl_removeHandleFromPipeline(easy->easy_handle, |           Curl_removeHandleFromPipeline(easy->easy_handle, | ||||||
|                                         easy->easy_conn->recv_pipe); |                                         easy->easy_conn->recv_pipe); | ||||||
|  |           /* Check if we can move pending requests to send pipe */ | ||||||
|  |           checkPendPipeline(easy->easy_conn); | ||||||
|  |           easy->easy_handle->state.is_in_pipeline = FALSE; | ||||||
|           if(!retry) { |           if(!retry) { | ||||||
|             /* if the URL is a follow-location and not just a retried request |             /* if the URL is a follow-location and not just a retried request | ||||||
|                then figure out the URL here */ |                then figure out the URL here */ | ||||||
|             newurl = easy->easy_handle->reqdata.newurl; |             newurl = easy->easy_handle->req.newurl; | ||||||
|             easy->easy_handle->reqdata.newurl = NULL; |             easy->easy_handle->req.newurl = NULL; | ||||||
|           } |           } | ||||||
|           easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); |           easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); | ||||||
|           if(easy->result == CURLE_OK) |           if(easy->result == CURLE_OK) | ||||||
| @@ -1330,6 +1343,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|       /* Remove ourselves from the receive pipeline */ |       /* Remove ourselves from the receive pipeline */ | ||||||
|       Curl_removeHandleFromPipeline(easy->easy_handle, |       Curl_removeHandleFromPipeline(easy->easy_handle, | ||||||
|                                     easy->easy_conn->recv_pipe); |                                     easy->easy_conn->recv_pipe); | ||||||
|  |       /* Check if we can move pending requests to send pipe */ | ||||||
|  |       checkPendPipeline(easy->easy_conn); | ||||||
|       easy->easy_handle->state.is_in_pipeline = FALSE; |       easy->easy_handle->state.is_in_pipeline = FALSE; | ||||||
|  |  | ||||||
|       if(easy->easy_conn->bits.stream_was_rewound) { |       if(easy->easy_conn->bits.stream_was_rewound) { | ||||||
| @@ -1339,22 +1354,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|           result = CURLM_CALL_MULTI_PERFORM; |           result = CURLM_CALL_MULTI_PERFORM; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (!easy->easy_handle->state.cancelled) { |  | ||||||
|       /* post-transfer command */ |       /* post-transfer command */ | ||||||
|       easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); |       easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); | ||||||
|  |  | ||||||
|       /* after we have DONE what we're supposed to do, go COMPLETED, and |       /* after we have DONE what we're supposed to do, go COMPLETED, and | ||||||
|          it doesn't matter what the Curl_done() returned! */ |          it doesn't matter what the Curl_done() returned! */ | ||||||
|       multistate(easy, CURLM_STATE_COMPLETED); |       multistate(easy, CURLM_STATE_COMPLETED); | ||||||
|       } |  | ||||||
|  |  | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case CURLM_STATE_COMPLETED: |     case CURLM_STATE_COMPLETED: | ||||||
|       if (easy->easy_handle->state.cancelled) |  | ||||||
|         /* Go into the CANCELLED state if we were cancelled */ |  | ||||||
|         multistate(easy, CURLM_STATE_CANCELLED); |  | ||||||
|  |  | ||||||
|       /* this is a completed transfer, it is likely to still be connected */ |       /* this is a completed transfer, it is likely to still be connected */ | ||||||
|  |  | ||||||
|       /* This node should be delinked from the list now and we should post |       /* This node should be delinked from the list now and we should post | ||||||
| @@ -1365,13 +1374,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|       easy->easy_conn = NULL; |       easy->easy_conn = NULL; | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case CURLM_STATE_CANCELLED: |  | ||||||
|       /* Cancelled transfer, wait to be cleaned up */ |  | ||||||
|  |  | ||||||
|       /* Reset the conn pointer so we don't leave it dangling */ |  | ||||||
|       easy->easy_conn = NULL; |  | ||||||
|       break; |  | ||||||
|  |  | ||||||
|     default: |     default: | ||||||
|       return CURLM_INTERNAL_ERROR; |       return CURLM_INTERNAL_ERROR; | ||||||
|     } |     } | ||||||
| @@ -1397,6 +1399,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | |||||||
|                                         easy->easy_conn->send_pipe); |                                         easy->easy_conn->send_pipe); | ||||||
|           Curl_removeHandleFromPipeline(easy->easy_handle, |           Curl_removeHandleFromPipeline(easy->easy_handle, | ||||||
|                                         easy->easy_conn->recv_pipe); |                                         easy->easy_conn->recv_pipe); | ||||||
|  |           /* Check if we can move pending requests to send pipe */ | ||||||
|  |           checkPendPipeline(easy->easy_conn); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(disconnect_conn) { |         if(disconnect_conn) { | ||||||
| @@ -1467,15 +1471,6 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) | |||||||
|   while(easy != &multi->easy) { |   while(easy != &multi->easy) { | ||||||
|     CURLMcode result; |     CURLMcode result; | ||||||
|  |  | ||||||
|     if (easy->easy_handle->state.cancelled && |  | ||||||
|         easy->state == CURLM_STATE_CANCELLED) { |  | ||||||
|       /* Remove cancelled handles once it's safe to do so */ |  | ||||||
|       Curl_multi_rmeasy(multi_handle, easy->easy_handle); |  | ||||||
|       easy->easy_handle = NULL; |  | ||||||
|       easy = easy->next; |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     result = multi_runsingle(multi, easy); |     result = multi_runsingle(multi, easy); | ||||||
|     if(result) |     if(result) | ||||||
|       returncode = result; |       returncode = result; | ||||||
| @@ -1959,6 +1954,77 @@ static int update_timer(struct Curl_multi *multi) | |||||||
|   return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp); |   return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle, | ||||||
|  |                                               struct connectdata *conn) | ||||||
|  | { | ||||||
|  |   size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; | ||||||
|  |   struct curl_llist *pipeline; | ||||||
|  |  | ||||||
|  |   if(!Curl_isPipeliningEnabled(handle) || | ||||||
|  |      pipeLen == 0) | ||||||
|  |     pipeline = conn->send_pipe; | ||||||
|  |   else { | ||||||
|  |     if(conn->server_supports_pipelining && | ||||||
|  |        pipeLen < MAX_PIPELINE_LENGTH) | ||||||
|  |       pipeline = conn->send_pipe; | ||||||
|  |     else | ||||||
|  |       pipeline = conn->pend_pipe; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return Curl_addHandleToPipeline(handle, pipeline); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int checkPendPipeline(struct connectdata *conn) | ||||||
|  | { | ||||||
|  |   int result = 0; | ||||||
|  |  | ||||||
|  |   if (conn->server_supports_pipelining) { | ||||||
|  |     size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; | ||||||
|  |     struct curl_llist_element *curr = conn->pend_pipe->head; | ||||||
|  |  | ||||||
|  |     while(pipeLen < MAX_PIPELINE_LENGTH && curr) { | ||||||
|  |       Curl_llist_move(conn->pend_pipe, curr, | ||||||
|  |                       conn->send_pipe, conn->send_pipe->tail); | ||||||
|  |       Curl_pgrsTime(curr->ptr, TIMER_CONNECT); | ||||||
|  |       ++result; /* count how many handles we moved */ | ||||||
|  |       curr = conn->pend_pipe->head; | ||||||
|  |       ++pipeLen; | ||||||
|  |     } | ||||||
|  |     if (result > 0) | ||||||
|  |       conn->now = Curl_tvnow(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int moveHandleFromSendToRecvPipeline(struct SessionHandle *handle, | ||||||
|  |                                             struct connectdata *conn) | ||||||
|  | { | ||||||
|  |   struct curl_llist_element *curr; | ||||||
|  |  | ||||||
|  |   curr = conn->send_pipe->head; | ||||||
|  |   while(curr) { | ||||||
|  |     if(curr->ptr == handle) { | ||||||
|  |       Curl_llist_move(conn->send_pipe, curr, | ||||||
|  |                       conn->recv_pipe, conn->recv_pipe->tail); | ||||||
|  |       return 1; /* we moved a handle */ | ||||||
|  |     } | ||||||
|  |     curr = curr->next; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool isHandleAtHead(struct SessionHandle *handle, | ||||||
|  |                            struct curl_llist *pipeline) | ||||||
|  | { | ||||||
|  |   struct curl_llist_element *curr = pipeline->head; | ||||||
|  |   if(curr) | ||||||
|  |     return (bool)(curr->ptr == handle); | ||||||
|  |  | ||||||
|  |   return FALSE; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* given a number of milliseconds from now to use to set the 'act before | /* given a number of milliseconds from now to use to set the 'act before | ||||||
|    this'-time for the transfer, to be extracted by curl_multi_timeout() */ |    this'-time for the transfer, to be extracted by curl_multi_timeout() */ | ||||||
| void Curl_expire(struct SessionHandle *data, long milli) | void Curl_expire(struct SessionHandle *data, long milli) | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								lib/nss.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/nss.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -436,10 +436,10 @@ static int display_error(struct connectdata *conn, PRInt32 err, | |||||||
| { | { | ||||||
|   switch(err) { |   switch(err) { | ||||||
|   case SEC_ERROR_BAD_PASSWORD: |   case SEC_ERROR_BAD_PASSWORD: | ||||||
|     failf(conn->data, "Unable to load client key: Incorrect password\n"); |     failf(conn->data, "Unable to load client key: Incorrect password"); | ||||||
|     return 1; |     return 1; | ||||||
|   case SEC_ERROR_UNKNOWN_CERT: |   case SEC_ERROR_UNKNOWN_CERT: | ||||||
|     failf(conn->data, "Unable to load certificate %s\n", filename); |     failf(conn->data, "Unable to load certificate %s", filename); | ||||||
|     return 1; |     return 1; | ||||||
|   default: |   default: | ||||||
|     break; |     break; | ||||||
| @@ -521,10 +521,10 @@ static SECStatus nss_Init_Tokens(struct connectdata * conn) | |||||||
|  |  | ||||||
|     if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) { |     if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) { | ||||||
|       if(slot == PK11_GetInternalKeySlot()) { |       if(slot == PK11_GetInternalKeySlot()) { | ||||||
|         failf(conn->data, "The NSS database has not been initialized.\n"); |         failf(conn->data, "The NSS database has not been initialized"); | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         failf(conn->data, "The token %s has not been initialized.", |         failf(conn->data, "The token %s has not been initialized", | ||||||
|               PK11_GetTokenName(slot)); |               PK11_GetTokenName(slot)); | ||||||
|       } |       } | ||||||
|       PK11_FreeSlot(slot); |       PK11_FreeSlot(slot); | ||||||
| @@ -1057,7 +1057,7 @@ int Curl_nss_send(struct connectdata *conn,  /* connection data */ | |||||||
|       return CURLE_OPERATION_TIMEDOUT; |       return CURLE_OPERATION_TIMEDOUT; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     failf(conn->data, "SSL write: error %d\n", err); |     failf(conn->data, "SSL write: error %d", err); | ||||||
|     return -1; |     return -1; | ||||||
|   } |   } | ||||||
|   return rc; /* number of bytes */ |   return rc; /* number of bytes */ | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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,8 +35,6 @@ | |||||||
| #include <nks/thread.h> | #include <nks/thread.h> | ||||||
| #include <nks/synch.h> | #include <nks/synch.h> | ||||||
|  |  | ||||||
| #include "memory.h" |  | ||||||
| #include "memdebug.h" |  | ||||||
|  |  | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -84,7 +84,7 @@ | |||||||
|  |  | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
|  |  | ||||||
| static time_t Curl_parsedate(const char *date); | static time_t parsedate(const char *date); | ||||||
|  |  | ||||||
| const char * const Curl_wkday[] = | const char * const Curl_wkday[] = | ||||||
| {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; | {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; | ||||||
| @@ -154,7 +154,7 @@ static const struct tzinfo tz[]= { | |||||||
|    0 monday - 6 sunday |    0 monday - 6 sunday | ||||||
| */ | */ | ||||||
|  |  | ||||||
| static int checkday(char *check, size_t len) | static int checkday(const char *check, size_t len) | ||||||
| { | { | ||||||
|   int i; |   int i; | ||||||
|   const char * const *what; |   const char * const *what; | ||||||
| @@ -173,7 +173,7 @@ static int checkday(char *check, size_t len) | |||||||
|   return found?i:-1; |   return found?i:-1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int checkmonth(char *check) | static int checkmonth(const char *check) | ||||||
| { | { | ||||||
|   int i; |   int i; | ||||||
|   const char * const *what; |   const char * const *what; | ||||||
| @@ -193,7 +193,7 @@ static int checkmonth(char *check) | |||||||
| /* return the time zone offset between GMT and the input one, in number | /* return the time zone offset between GMT and the input one, in number | ||||||
|    of seconds or -1 if the timezone wasn't found/legal */ |    of seconds or -1 if the timezone wasn't found/legal */ | ||||||
|  |  | ||||||
| static int checktz(char *check) | static int checktz(const char *check) | ||||||
| { | { | ||||||
|   unsigned int i; |   unsigned int i; | ||||||
|   const struct tzinfo *what; |   const struct tzinfo *what; | ||||||
| @@ -223,7 +223,7 @@ enum assume { | |||||||
|   DATE_TIME |   DATE_TIME | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static time_t Curl_parsedate(const char *date) | static time_t parsedate(const char *date) | ||||||
| { | { | ||||||
|   time_t t = 0; |   time_t t = 0; | ||||||
|   int wdaynum=-1;  /* day of the week number, 0-6 (mon-sun) */ |   int wdaynum=-1;  /* day of the week number, 0-6 (mon-sun) */ | ||||||
| @@ -289,11 +289,17 @@ static time_t Curl_parsedate(const char *date) | |||||||
|  |  | ||||||
|         if((tzoff == -1) && |         if((tzoff == -1) && | ||||||
|            ((end - date) == 4) && |            ((end - date) == 4) && | ||||||
|            (val < 1300) && |            (val <= 1400) && | ||||||
|            (indate< date) && |            (indate< date) && | ||||||
|            ((date[-1] == '+' || date[-1] == '-'))) { |            ((date[-1] == '+' || date[-1] == '-'))) { | ||||||
|           /* four digits and a value less than 1300 and it is preceeded with |           /* four digits and a value less than or equal to 1400 (to take into | ||||||
|              a plus or minus. This is a time zone indication. */ |              account all sorts of funny time zone diffs) and it is preceeded | ||||||
|  |              with a plus or minus. This is a time zone indication.  1400 is | ||||||
|  |              picked since +1300 is frequently used and +1400 is mentioned as | ||||||
|  |              an edge number in the document "ISO C 200X Proposal: Timezone | ||||||
|  |              Functions" at http://david.tribble.com/text/c0xtimezone.html If | ||||||
|  |              anyone has a more authoritative source for the exact maximum time | ||||||
|  |              zone offsets, please speak up! */ | ||||||
|           found = TRUE; |           found = TRUE; | ||||||
|           tzoff = (val/100 * 60 + val%100)*60; |           tzoff = (val/100 * 60 + val%100)*60; | ||||||
|  |  | ||||||
| @@ -421,5 +427,5 @@ static time_t Curl_parsedate(const char *date) | |||||||
| time_t curl_getdate(const char *p, const time_t *now) | time_t curl_getdate(const char *p, const time_t *now) | ||||||
| { | { | ||||||
|   (void)now; |   (void)now; | ||||||
|   return Curl_parsedate(p); |   return parsedate(p); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -356,11 +356,10 @@ int Curl_pgrsUpdate(struct connectdata *conn) | |||||||
|        progress */ |        progress */ | ||||||
|  |  | ||||||
|     if(!(data->progress.flags & PGRS_HEADERS_OUT)) { |     if(!(data->progress.flags & PGRS_HEADERS_OUT)) { | ||||||
|       if(data->reqdata.resume_from) { |       if(data->state.resume_from) { | ||||||
|         fprintf(data->set.err, |         fprintf(data->set.err, | ||||||
|                 "** Resuming transfer from byte position %" FORMAT_OFF_T |                 "** Resuming transfer from byte position %" FORMAT_OFF_T "\n", | ||||||
|                 "\n", |                 data->state.resume_from); | ||||||
|                 data->reqdata.resume_from); |  | ||||||
|       } |       } | ||||||
|       fprintf(data->set.err, |       fprintf(data->set.err, | ||||||
|               "  %% Total    %% Received %% Xferd  Average Speed   Time    Time     Time  Current\n" |               "  %% Total    %% Received %% Xferd  Average Speed   Time    Time     Time  Current\n" | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								lib/qssl.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								lib/qssl.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -108,7 +108,7 @@ static CURLcode Curl_qsossl_init_session(struct SessionHandle * data) | |||||||
|     break; |     break; | ||||||
|  |  | ||||||
|   case SSL_ERROR_IO: |   case SSL_ERROR_IO: | ||||||
|     failf(data, "SSL_Init() I/O error: %s\n", strerror(errno)); |     failf(data, "SSL_Init() I/O error: %s", strerror(errno)); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|  |  | ||||||
|   case SSL_ERROR_BAD_CIPHER_SUITE: |   case SSL_ERROR_BAD_CIPHER_SUITE: | ||||||
| @@ -125,7 +125,7 @@ static CURLcode Curl_qsossl_init_session(struct SessionHandle * data) | |||||||
|     return CURLE_SSL_CERTPROBLEM; |     return CURLE_SSL_CERTPROBLEM; | ||||||
|  |  | ||||||
|   default: |   default: | ||||||
|     failf(data, "SSL_Init(): %s\n", SSL_Strerror(rc, NULL)); |     failf(data, "SSL_Init(): %s", SSL_Strerror(rc, NULL)); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -142,7 +142,7 @@ static CURLcode Curl_qsossl_create(struct connectdata * conn, int sockindex) | |||||||
|   h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT); |   h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT); | ||||||
|  |  | ||||||
|   if(!h) { |   if(!h) { | ||||||
|     failf(conn->data, "SSL_Create() I/O error: %s\n", strerror(errno)); |     failf(conn->data, "SSL_Create() I/O error: %s", strerror(errno)); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -232,11 +232,11 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex) | |||||||
|     return CURLE_SSL_CERTPROBLEM; |     return CURLE_SSL_CERTPROBLEM; | ||||||
|  |  | ||||||
|   case SSL_ERROR_IO: |   case SSL_ERROR_IO: | ||||||
|     failf(data, "SSL_Handshake(): %s\n", SSL_Strerror(rc, NULL)); |     failf(data, "SSL_Handshake(): %s", SSL_Strerror(rc, NULL)); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|  |  | ||||||
|   default: |   default: | ||||||
|     failf(data, "SSL_Init(): %s\n", SSL_Strerror(rc, NULL)); |     failf(data, "SSL_Init(): %s", SSL_Strerror(rc, NULL)); | ||||||
|     return CURLE_SSL_CONNECT_ERROR; |     return CURLE_SSL_CONNECT_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -282,12 +282,12 @@ static int Curl_qsossl_close_one(struct ssl_connect_data * conn, | |||||||
|  |  | ||||||
|   if(rc) { |   if(rc) { | ||||||
|     if(rc == SSL_ERROR_IO) { |     if(rc == SSL_ERROR_IO) { | ||||||
|       failf(data, "SSL_Destroy() I/O error: %s\n", strerror(errno)); |       failf(data, "SSL_Destroy() I/O error: %s", strerror(errno)); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* An SSL error. */ |     /* An SSL error. */ | ||||||
|     failf(data, "SSL_Destroy() returned error %d\n", SSL_Strerror(rc, NULL)); |     failf(data, "SSL_Destroy() returned error %d", SSL_Strerror(rc, NULL)); | ||||||
|     return -1; |     return -1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -359,7 +359,7 @@ int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex) | |||||||
|     nread = read(conn->sock[sockindex], buf, sizeof(buf)); |     nread = read(conn->sock[sockindex], buf, sizeof(buf)); | ||||||
|  |  | ||||||
|     if(nread < 0) { |     if(nread < 0) { | ||||||
|       failf(data, "read: %s\n", strerror(errno)); |       failf(data, "read: %s", strerror(errno)); | ||||||
|       rc = -1; |       rc = -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -399,12 +399,12 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex, void * mem, | |||||||
|         return 0; |         return 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|       failf(conn->data, "SSL_Write() I/O error: %s\n", strerror(errno)); |       failf(conn->data, "SSL_Write() I/O error: %s", strerror(errno)); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* An SSL error. */ |     /* An SSL error. */ | ||||||
|     failf(conn->data, "SSL_Write() returned error %d\n", |     failf(conn->data, "SSL_Write() returned error %d", | ||||||
|           SSL_Strerror(rc, NULL)); |           SSL_Strerror(rc, NULL)); | ||||||
|     return -1; |     return -1; | ||||||
|   } |   } | ||||||
| @@ -442,11 +442,11 @@ ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf, | |||||||
|         return -1; |         return -1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|       failf(conn->data, "SSL_Read() I/O error: %s\n", strerror(errno)); |       failf(conn->data, "SSL_Read() I/O error: %s", strerror(errno)); | ||||||
|       return -1; |       return -1; | ||||||
|  |  | ||||||
|     default: |     default: | ||||||
|       failf(conn->data, "SSL read error: %s\n", SSL_Strerror(nread, NULL)); |       failf(conn->data, "SSL read error: %s", SSL_Strerror(nread, NULL)); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -9,6 +9,9 @@ | |||||||
|  * |  * | ||||||
|  * Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan |  * Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan | ||||||
|  * (Royal Institute of Technology, Stockholm, Sweden). |  * (Royal Institute of Technology, Stockholm, Sweden). | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2001 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
|  * |  * | ||||||
|  * Redistribution and use in source and binary forms, with or without |  * Redistribution and use in source and binary forms, with or without | ||||||
| @@ -260,10 +263,12 @@ sec_send(struct connectdata *conn, int fd, char *from, int length) | |||||||
|         block_write(fd, "MIC ", 4); |         block_write(fd, "MIC ", 4); | ||||||
|       block_write(fd, cmdbuf, bytes); |       block_write(fd, cmdbuf, bytes); | ||||||
|       block_write(fd, "\r\n", 2); |       block_write(fd, "\r\n", 2); | ||||||
|       Curl_infof(conn->data, "%s %s\n", protlevel == prot_private ? "ENC" : "MIC", cmdbuf); |       Curl_infof(conn->data, "%s %s\n", | ||||||
|  |                  protlevel == prot_private ? "ENC" : "MIC", cmdbuf); | ||||||
|       free(cmdbuf); |       free(cmdbuf); | ||||||
|     } |     } | ||||||
|   } else { |   } | ||||||
|  |   else { | ||||||
|     bytes = htonl(bytes); |     bytes = htonl(bytes); | ||||||
|     block_write(fd, &bytes, sizeof(bytes)); |     block_write(fd, &bytes, sizeof(bytes)); | ||||||
|     block_write(fd, buf, ntohl(bytes)); |     block_write(fd, buf, ntohl(bytes)); | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								lib/select.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								lib/select.h
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -27,6 +27,8 @@ | |||||||
|  |  | ||||||
| #ifdef HAVE_SYS_POLL_H | #ifdef HAVE_SYS_POLL_H | ||||||
| #include <sys/poll.h> | #include <sys/poll.h> | ||||||
|  | #elif defined(HAVE_POLL_H) | ||||||
|  | #include <poll.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -40,13 +42,18 @@ | |||||||
| #undef  HAVE_POLL_FINE | #undef  HAVE_POLL_FINE | ||||||
| #define HAVE_POLL_FINE 1 | #define HAVE_POLL_FINE 1 | ||||||
| #define poll(x,y,z) WSAPoll((x),(y),(z)) | #define poll(x,y,z) WSAPoll((x),(y),(z)) | ||||||
|  | #if defined(_MSC_VER) && defined(POLLRDNORM) | ||||||
|  | #define HAVE_STRUCT_POLLFD 1 | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Definition of pollfd struct and constants for platforms lacking them. |  * Definition of pollfd struct and constants for platforms lacking them. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef HAVE_SYS_POLL_H | #if !defined(HAVE_STRUCT_POLLFD) && \ | ||||||
|  |     !defined(HAVE_SYS_POLL_H) && \ | ||||||
|  |     !defined(HAVE_POLL_H) | ||||||
|  |  | ||||||
| #define POLLIN      0x01 | #define POLLIN      0x01 | ||||||
| #define POLLPRI     0x02 | #define POLLPRI     0x02 | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								lib/sendf.c
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								lib/sendf.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -160,7 +160,7 @@ static size_t convert_lineends(struct SessionHandle *data, | |||||||
|     if(*startPtr == '\n') { |     if(*startPtr == '\n') { | ||||||
|       /* This block of incoming data starts with the |       /* This block of incoming data starts with the | ||||||
|          previous block's LF so get rid of it */ |          previous block's LF so get rid of it */ | ||||||
|       memcpy(startPtr, startPtr+1, size-1); |       memmove(startPtr, startPtr+1, size-1); | ||||||
|       size--; |       size--; | ||||||
|       /* and it wasn't a bare CR but a CRLF conversion instead */ |       /* and it wasn't a bare CR but a CRLF conversion instead */ | ||||||
|       data->state.crlf_conversions++; |       data->state.crlf_conversions++; | ||||||
| @@ -310,7 +310,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, | |||||||
|   return res; |   return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| static ssize_t Curl_plain_send(struct connectdata *conn, | static ssize_t send_plain(struct connectdata *conn, | ||||||
|                           int num, |                           int num, | ||||||
|                           void *mem, |                           void *mem, | ||||||
|                           size_t len) |                           size_t len) | ||||||
| @@ -368,7 +368,7 @@ CURLcode Curl_write(struct connectdata *conn, | |||||||
|     /* only TRUE if krb enabled */ |     /* only TRUE if krb enabled */ | ||||||
|     bytes_written = Curl_sec_send(conn, num, mem, len); |     bytes_written = Curl_sec_send(conn, num, mem, len); | ||||||
|   else |   else | ||||||
|     bytes_written = Curl_plain_send(conn, num, mem, len); |     bytes_written = send_plain(conn, num, mem, len); | ||||||
|  |  | ||||||
|   *written = bytes_written; |   *written = bytes_written; | ||||||
|   retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR; |   retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR; | ||||||
| @@ -376,6 +376,36 @@ CURLcode Curl_write(struct connectdata *conn, | |||||||
|   return retcode; |   return retcode; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static CURLcode pausewrite(struct SessionHandle *data, | ||||||
|  |                            int type, /* what type of data */ | ||||||
|  |                            char *ptr, | ||||||
|  |                            size_t len) | ||||||
|  | { | ||||||
|  |   /* signalled to pause sending on this connection, but since we have data | ||||||
|  |      we want to send we need to dup it to save a copy for when the sending | ||||||
|  |      is again enabled */ | ||||||
|  |   struct SingleRequest *k = &data->req; | ||||||
|  |   char *dupl = malloc(len); | ||||||
|  |   if(!dupl) | ||||||
|  |     return CURLE_OUT_OF_MEMORY; | ||||||
|  |  | ||||||
|  |   memcpy(dupl, ptr, len); | ||||||
|  |  | ||||||
|  |   /* store this information in the state struct for later use */ | ||||||
|  |   data->state.tempwrite = dupl; | ||||||
|  |   data->state.tempwritesize = len; | ||||||
|  |   data->state.tempwritetype = type; | ||||||
|  |  | ||||||
|  |   /* mark the connection as RECV paused */ | ||||||
|  |   k->keepon |= KEEP_READ_PAUSE; | ||||||
|  |  | ||||||
|  |   DEBUGF(infof(data, "Pausing with %d bytes in buffer for type %02x\n", | ||||||
|  |                (int)len, type)); | ||||||
|  |  | ||||||
|  |   return CURLE_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* client_write() sends data to the write callback(s) | /* client_write() sends data to the write callback(s) | ||||||
|  |  | ||||||
|    The bit pattern defines to what "streams" to write to. Body and/or header. |    The bit pattern defines to what "streams" to write to. Body and/or header. | ||||||
| @@ -389,8 +419,32 @@ CURLcode Curl_client_write(struct connectdata *conn, | |||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   size_t wrote; |   size_t wrote; | ||||||
|  |  | ||||||
|   if (data->state.cancelled) { |   /* If reading is actually paused, we're forced to append this chunk of data | ||||||
|       /* We just suck everything into a black hole */ |      to the already held data, but only if it is the same type as otherwise it | ||||||
|  |      can't work and it'll return error instead. */ | ||||||
|  |   if(data->req.keepon & KEEP_READ_PAUSE) { | ||||||
|  |     size_t newlen; | ||||||
|  |     char *newptr; | ||||||
|  |     if(type != data->state.tempwritetype) | ||||||
|  |       /* major internal confusion */ | ||||||
|  |       return CURLE_RECV_ERROR; | ||||||
|  |  | ||||||
|  |     /* figure out the new size of the data to save */ | ||||||
|  |     newlen = len + data->state.tempwritesize; | ||||||
|  |     /* allocate the new memory area */ | ||||||
|  |     newptr = malloc(newlen); | ||||||
|  |     if(!newptr) | ||||||
|  |       return CURLE_OUT_OF_MEMORY; | ||||||
|  |     /* copy the previously held data to the new area */ | ||||||
|  |     memcpy(newptr, data->state.tempwrite, data->state.tempwritesize); | ||||||
|  |     /* copy the new data to the end of the new area */ | ||||||
|  |     memcpy(newptr + data->state.tempwritesize, ptr, len); | ||||||
|  |     /* free the old data */ | ||||||
|  |     free(data->state.tempwrite); | ||||||
|  |     /* update the pointer and the size */ | ||||||
|  |     data->state.tempwrite = newptr; | ||||||
|  |     data->state.tempwritesize = newlen; | ||||||
|  |  | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -422,8 +476,11 @@ CURLcode Curl_client_write(struct connectdata *conn, | |||||||
|       wrote = len; |       wrote = len; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if(CURL_WRITEFUNC_PAUSE == wrote) | ||||||
|  |       return pausewrite(data, type, ptr, len); | ||||||
|  |  | ||||||
|     if(wrote != len) { |     if(wrote != len) { | ||||||
|       failf (data, "Failed writing body"); |       failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len); | ||||||
|       return CURLE_WRITE_ERROR; |       return CURLE_WRITE_ERROR; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -441,6 +498,12 @@ CURLcode Curl_client_write(struct connectdata *conn, | |||||||
|        regardless of the ftp transfer mode (ASCII/Image) */ |        regardless of the ftp transfer mode (ASCII/Image) */ | ||||||
|  |  | ||||||
|     wrote = writeit(ptr, 1, len, data->set.writeheader); |     wrote = writeit(ptr, 1, len, data->set.writeheader); | ||||||
|  |     if(CURL_WRITEFUNC_PAUSE == wrote) | ||||||
|  |       /* here we pass in the HEADER bit only since if this was body as well | ||||||
|  |          then it was passed already and clearly that didn't trigger the pause, | ||||||
|  |          so this is saved for later with the HEADER bit only */ | ||||||
|  |       return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); | ||||||
|  |  | ||||||
|     if(wrote != len) { |     if(wrote != len) { | ||||||
|       failf (data, "Failed writing header"); |       failf (data, "Failed writing header"); | ||||||
|       return CURLE_WRITE_ERROR; |       return CURLE_WRITE_ERROR; | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								lib/setup.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								lib/setup.h
									
									
									
									
									
								
							| @@ -32,13 +32,11 @@ | |||||||
| #define CURL_DISABLE_FILE | #define CURL_DISABLE_FILE | ||||||
| #endif /* HTTP_ONLY */ | #endif /* HTTP_ONLY */ | ||||||
|  |  | ||||||
| #if !defined(WIN32) && defined(__WIN32__) | /* | ||||||
| /* Borland fix */ |  * Define WIN32 when build target is Win32 API | ||||||
| #define WIN32 |  */ | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if !defined(WIN32) && defined(_WIN32) | #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) | ||||||
| /* VS2005 on x64 fix */ |  | ||||||
| #define WIN32 | #define WIN32 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2007, 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 | ||||||
|   | |||||||
							
								
								
									
										119
									
								
								lib/socks.c
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								lib/socks.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___ |  *                            | (__| |_| |  _ <| |___ | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 1998 - 2008, 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 | ||||||
| @@ -118,16 +118,19 @@ static int blockread_all(struct connectdata *conn, /* connection data */ | |||||||
| *   http://socks.permeo.com/protocol/socks4.protocol | *   http://socks.permeo.com/protocol/socks4.protocol | ||||||
| * | * | ||||||
| * Note : | * Note : | ||||||
| *   Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" | *   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" | ||||||
| *   Nonsupport "Identification Protocol (RFC1413)" | *   Nonsupport "Identification Protocol (RFC1413)" | ||||||
| */ | */ | ||||||
| CURLcode Curl_SOCKS4(const char *proxy_name, | CURLcode Curl_SOCKS4(const char *proxy_name, | ||||||
|                      const char *hostname, |                      const char *hostname, | ||||||
|                      int remote_port, |                      int remote_port, | ||||||
|                      int sockindex, |                      int sockindex, | ||||||
|                      struct connectdata *conn) |                      struct connectdata *conn, | ||||||
|  |                      bool protocol4a) | ||||||
| { | { | ||||||
|   unsigned char socksreq[262]; /* room for SOCKS4 request incl. user id */ | #define SOCKS4REQLEN 262 | ||||||
|  |   unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user | ||||||
|  |                                            id */ | ||||||
|   int result; |   int result; | ||||||
|   CURLcode code; |   CURLcode code; | ||||||
|   curl_socket_t sock = conn->sock[sockindex]; |   curl_socket_t sock = conn->sock[sockindex]; | ||||||
| @@ -165,8 +168,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name, | |||||||
|   socksreq[1] = 1; /* connect */ |   socksreq[1] = 1; /* connect */ | ||||||
|   *((unsigned short*)&socksreq[2]) = htons((unsigned short)remote_port); |   *((unsigned short*)&socksreq[2]) = htons((unsigned short)remote_port); | ||||||
|  |  | ||||||
|   /* DNS resolve */ |   /* DNS resolve only for SOCKS4, not SOCKS4a */ | ||||||
|   { |   if (!protocol4a) { | ||||||
|     struct Curl_dns_entry *dns; |     struct Curl_dns_entry *dns; | ||||||
|     Curl_addrinfo *hp=NULL; |     Curl_addrinfo *hp=NULL; | ||||||
|     int rc; |     int rc; | ||||||
| @@ -225,15 +228,40 @@ CURLcode Curl_SOCKS4(const char *proxy_name, | |||||||
|   { |   { | ||||||
|     ssize_t actualread; |     ssize_t actualread; | ||||||
|     ssize_t written; |     ssize_t written; | ||||||
|  |     ssize_t hostnamelen = 0; | ||||||
|     int packetsize = 9 + |     int packetsize = 9 + | ||||||
|       (int)strlen((char*)socksreq + 8); /* size including NUL */ |       (int)strlen((char*)socksreq + 8); /* size including NUL */ | ||||||
|  |  | ||||||
|  |     /* If SOCKS4a, set special invalid IP address 0.0.0.x */ | ||||||
|  |     if (protocol4a) { | ||||||
|  |       socksreq[4] = 0; | ||||||
|  |       socksreq[5] = 0; | ||||||
|  |       socksreq[6] = 0; | ||||||
|  |       socksreq[7] = 1; | ||||||
|  |       /* If still enough room in buffer, also append hostname */ | ||||||
|  |       hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ | ||||||
|  |       if (packetsize + hostnamelen <= SOCKS4REQLEN) | ||||||
|  |         strcpy((char*)socksreq + packetsize, hostname); | ||||||
|  |       else | ||||||
|  |         hostnamelen = 0; /* Flag: hostname did not fit in buffer */ | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Send request */ |     /* Send request */ | ||||||
|     code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written); |     code = Curl_write(conn, sock, (char *)socksreq, packetsize + hostnamelen, | ||||||
|     if ((code != CURLE_OK) || (written != packetsize)) { |                       &written); | ||||||
|  |     if((code != CURLE_OK) || (written != packetsize + hostnamelen)) { | ||||||
|       failf(data, "Failed to send SOCKS4 connect request."); |       failf(data, "Failed to send SOCKS4 connect request."); | ||||||
|       return CURLE_COULDNT_CONNECT; |       return CURLE_COULDNT_CONNECT; | ||||||
|     } |     } | ||||||
|  |     if (protocol4a && hostnamelen == 0) { | ||||||
|  |       /* SOCKS4a with very long hostname - send that name separately */ | ||||||
|  |       hostnamelen = (ssize_t)strlen(hostname) + 1; | ||||||
|  |       code = Curl_write(conn, sock, (char *)hostname, hostnamelen, &written); | ||||||
|  |       if((code != CURLE_OK) || (written != hostnamelen)) { | ||||||
|  |         failf(data, "Failed to send SOCKS4 connect request."); | ||||||
|  |         return CURLE_COULDNT_CONNECT; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     packetsize = 8; /* receive data size */ |     packetsize = 8; /* receive data size */ | ||||||
|  |  | ||||||
| @@ -275,6 +303,9 @@ CURLcode Curl_SOCKS4(const char *proxy_name, | |||||||
|     switch(socksreq[1]) |     switch(socksreq[1]) | ||||||
|     { |     { | ||||||
|     case 90: |     case 90: | ||||||
|  |       if (protocol4a) | ||||||
|  |         infof(data, "SOCKS4a request granted.\n"); | ||||||
|  |       else | ||||||
|         infof(data, "SOCKS4 request granted.\n"); |         infof(data, "SOCKS4 request granted.\n"); | ||||||
|       break; |       break; | ||||||
|     case 91: |     case 91: | ||||||
| @@ -359,6 +390,17 @@ CURLcode Curl_SOCKS5(const char *proxy_name, | |||||||
|   curl_socket_t sock = conn->sock[sockindex]; |   curl_socket_t sock = conn->sock[sockindex]; | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   long timeout; |   long timeout; | ||||||
|  |   bool socks5_resolve_local = (bool)(data->set.proxytype == CURLPROXY_SOCKS5); | ||||||
|  |   const size_t hostname_len = strlen(hostname); | ||||||
|  |   ssize_t packetsize = 0; | ||||||
|  |  | ||||||
|  |   /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ | ||||||
|  |   if(!socks5_resolve_local && hostname_len > 255) | ||||||
|  |   { | ||||||
|  |     infof(conn->data,"SOCKS5: server resolving disabled for hostnames of " | ||||||
|  |           "length > 255 [actual len=%d]\n", hostname_len); | ||||||
|  |     socks5_resolve_local = TRUE; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* get timeout */ |   /* get timeout */ | ||||||
|   if(data->set.timeout && data->set.connecttimeout) { |   if(data->set.timeout && data->set.connecttimeout) { | ||||||
| @@ -522,13 +564,26 @@ CURLcode Curl_SOCKS5(const char *proxy_name, | |||||||
|   socksreq[0] = 5; /* version (SOCKS5) */ |   socksreq[0] = 5; /* version (SOCKS5) */ | ||||||
|   socksreq[1] = 1; /* connect */ |   socksreq[1] = 1; /* connect */ | ||||||
|   socksreq[2] = 0; /* must be zero */ |   socksreq[2] = 0; /* must be zero */ | ||||||
|   socksreq[3] = 1; /* IPv4 = 1 */ |  | ||||||
|  |  | ||||||
|   { |   if(!socks5_resolve_local) { | ||||||
|  |     packetsize = (ssize_t)(5 + hostname_len + 2); | ||||||
|  |  | ||||||
|  |     socksreq[3] = 3; /* ATYP: domain name = 3 */ | ||||||
|  |     socksreq[4] = (char) hostname_len; /* address length */ | ||||||
|  |     memcpy(&socksreq[5], hostname, hostname_len); /* address bytes w/o NULL */ | ||||||
|  |  | ||||||
|  |     *((unsigned short*)&socksreq[hostname_len+5]) = | ||||||
|  |       htons((unsigned short)remote_port); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|     struct Curl_dns_entry *dns; |     struct Curl_dns_entry *dns; | ||||||
|     Curl_addrinfo *hp=NULL; |     Curl_addrinfo *hp=NULL; | ||||||
|     int rc = Curl_resolv(conn, hostname, remote_port, &dns); |     int rc = Curl_resolv(conn, hostname, remote_port, &dns); | ||||||
|  |  | ||||||
|  |     packetsize = 10; | ||||||
|  |  | ||||||
|  |     socksreq[3] = 1; /* IPv4 = 1 */ | ||||||
|  |  | ||||||
|     if(rc == CURLRESOLV_ERROR) |     if(rc == CURLRESOLV_ERROR) | ||||||
|       return CURLE_COULDNT_RESOLVE_HOST; |       return CURLE_COULDNT_RESOLVE_HOST; | ||||||
|  |  | ||||||
| @@ -564,12 +619,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name, | |||||||
|             hostname); |             hostname); | ||||||
|       return CURLE_COULDNT_RESOLVE_HOST; |       return CURLE_COULDNT_RESOLVE_HOST; | ||||||
|     } |     } | ||||||
|   } |  | ||||||
|  |  | ||||||
|     *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port); |     *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port); | ||||||
|  |   } | ||||||
|   { |  | ||||||
|     const int packetsize = 10; |  | ||||||
|  |  | ||||||
|   code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written); |   code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written); | ||||||
|   if((code != CURLE_OK) || (written != packetsize)) { |   if((code != CURLE_OK) || (written != packetsize)) { | ||||||
| @@ -577,6 +629,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name, | |||||||
|     return CURLE_COULDNT_CONNECT; |     return CURLE_COULDNT_CONNECT; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   packetsize = 10; /* minimum packet size is 10 */ | ||||||
|  |  | ||||||
|   result = blockread_all(conn, sock, (char *)socksreq, packetsize, |   result = blockread_all(conn, sock, (char *)socksreq, packetsize, | ||||||
|                            &actualread, timeout); |                            &actualread, timeout); | ||||||
|   if((result != CURLE_OK) || (actualread != packetsize)) { |   if((result != CURLE_OK) || (actualread != packetsize)) { | ||||||
| @@ -598,6 +652,43 @@ CURLcode Curl_SOCKS5(const char *proxy_name, | |||||||
|             socksreq[1]); |             socksreq[1]); | ||||||
|       return CURLE_COULDNT_CONNECT; |       return CURLE_COULDNT_CONNECT; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /* Fix: in general, returned BND.ADDR is variable length parameter by RFC | ||||||
|  |      1928, so the reply packet should be read until the end to avoid errors at | ||||||
|  |      subsequent protocol level. | ||||||
|  |  | ||||||
|  |     +----+-----+-------+------+----------+----------+ | ||||||
|  |     |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT | | ||||||
|  |     +----+-----+-------+------+----------+----------+ | ||||||
|  |     | 1  |  1  | X'00' |  1   | Variable |    2     | | ||||||
|  |     +----+-----+-------+------+----------+----------+ | ||||||
|  |  | ||||||
|  |      ATYP: | ||||||
|  |      o  IP v4 address: X'01', BND.ADDR = 4 byte | ||||||
|  |      o  domain name:  X'03', BND.ADDR = [ 1 byte length, string ] | ||||||
|  |      o  IP v6 address: X'04', BND.ADDR = 16 byte | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |   /* Calculate real packet size */ | ||||||
|  |   if(socksreq[3] == 3) { | ||||||
|  |     /* domain name */ | ||||||
|  |     int addrlen = (int) socksreq[4]; | ||||||
|  |     packetsize = 5 + addrlen + 2; | ||||||
|  |   } | ||||||
|  |   else if(socksreq[3] == 4) { | ||||||
|  |     /* IPv6 */ | ||||||
|  |     packetsize = 4 + 16 + 2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* At this point we already read first 10 bytes */ | ||||||
|  |   if(packetsize > 10) { | ||||||
|  |     packetsize -= 10; | ||||||
|  |     result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize, | ||||||
|  |                            &actualread, timeout); | ||||||
|  |     if((result != CURLE_OK) || (actualread != packetsize)) { | ||||||
|  |       failf(data, "Failed to receive SOCKS5 connect request ack."); | ||||||
|  |       return CURLE_COULDNT_CONNECT; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Curl_nonblock(sock, TRUE); |   Curl_nonblock(sock, TRUE); | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user