Compare commits
	
		
			352 Commits
		
	
	
		
			curl-7_9_1
			...
			curl-7_9_5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b40b9677b6 | ||
|   | c80ad865db | ||
|   | 758eae49ab | ||
|   | 721b05e343 | ||
|   | a333bddeeb | ||
|   | 4c6a52fe90 | ||
|   | 792d73a9cf | ||
|   | 9a95a3f8c3 | ||
|   | 485edb777f | ||
|   | a8c3431ae9 | ||
|   | 6fe4a6fa9a | ||
|   | 6d8c7356d6 | ||
|   | a782c96e81 | ||
|   | c795123cd5 | ||
|   | 0ec370e6fb | ||
|   | 3d5732d4e0 | ||
|   | b795929858 | ||
|   | 535258ffe4 | ||
|   | cc161b96ac | ||
|   | 5c4b422b18 | ||
|   | 89bad584c3 | ||
|   | e21926f7f0 | ||
|   | e452f467d4 | ||
|   | dfda7ba456 | ||
|   | feb6b6445e | ||
|   | 0b57fa9c51 | ||
|   | 55c6f60c90 | ||
|   | 9def011e8e | ||
|   | 7cf6e8c9cc | ||
|   | cdee43aa59 | ||
|   | 9c25b58b4c | ||
|   | 83f35463f5 | ||
|   | 818cdb879e | ||
|   | 3eead2d6c4 | ||
|   | 5cffe055ad | ||
|   | 3d4511daf3 | ||
|   | 4748b40ad9 | ||
|   | c40b4f6c39 | ||
|   | d3b96dd394 | ||
|   | f946df640b | ||
|   | fef78bd6f1 | ||
|   | 9e6cc86bf7 | ||
|   | b544c5fa5c | ||
|   | afa64ee31f | ||
|   | e9bfef0eb1 | ||
|   | ddbcccd43d | ||
|   | 5370d7a6eb | ||
|   | 685b180ab6 | ||
|   | 9dab850874 | ||
|   | 0d5bfe883e | ||
|   | cc2f1d4894 | ||
|   | a8dd13db4c | ||
|   | 325391aef9 | ||
|   | 3474ec4ecb | ||
|   | ec1736d488 | ||
|   | 4522579688 | ||
|   | 907a6e0eed | ||
|   | d20186a7b8 | ||
|   | b28051881e | ||
|   | bdea56cd3f | ||
|   | 8a3ec2c659 | ||
|   | 14e9420d2c | ||
|   | 5b58e61f28 | ||
|   | be2f3071b5 | ||
|   | 85dbf82d93 | ||
|   | a9c4963cc0 | ||
|   | a4934387d5 | ||
|   | e88a2ec6fc | ||
|   | 0666960173 | ||
|   | f114caca90 | ||
|   | 9468c9c796 | ||
|   | 76c53c690c | ||
|   | c341b11aaf | ||
|   | 6212e6990a | ||
|   | 28049a183c | ||
|   | 5d3dd7911e | ||
|   | ae8375516b | ||
|   | e3f10eb825 | ||
|   | 2b1f683239 | ||
|   | a2b19c9a63 | ||
|   | 4146ce8267 | ||
|   | 170bd6dafc | ||
|   | 7e16ec8724 | ||
|   | 8c459156f8 | ||
|   | 2db894807b | ||
|   | 95ceeb6e0b | ||
|   | c9c00d2a23 | ||
|   | 1afe49864d | ||
|   | 6924bee3a0 | ||
|   | 39d4552dab | ||
|   | a23c63738f | ||
|   | e911945c55 | ||
|   | 6d58d13710 | ||
|   | 0b177cb165 | ||
|   | 3e31b619de | ||
|   | f925979b2f | ||
|   | 49f7fa82b9 | ||
|   | e4cd4cf3f3 | ||
|   | e74b20926d | ||
|   | a312127c91 | ||
|   | 1dc5bf4f73 | ||
|   | 01cfe670c5 | ||
|   | fd307bfe29 | ||
|   | a00de093a7 | ||
|   | 7bfe853af3 | ||
|   | cbaecca8e9 | ||
|   | 8edfb370a8 | ||
|   | 4c08c8f7db | ||
|   | c174680a03 | ||
|   | cb5f6e18e6 | ||
|   | b798e7a5ae | ||
|   | 5deab7ad27 | ||
|   | 12cdfd282d | ||
|   | eba8035e12 | ||
|   | edcbf4350b | ||
|   | 9289ea471f | ||
|   | 7d06185aa6 | ||
|   | 01ecb1d7e7 | ||
|   | e177f14595 | ||
|   | 5c6eddcadd | ||
|   | b3b4786990 | ||
|   | fbe2907599 | ||
|   | 343da8d4b3 | ||
|   | 8d97792dbc | ||
|   | 8d07c87be7 | ||
|   | ed21701df3 | ||
|   | df01507582 | ||
|   | f2bda5fd5b | ||
|   | cba9838e8f | ||
|   | b6dba9f5dd | ||
|   | 6e9d1617c6 | ||
|   | ea811fee52 | ||
|   | 7391fd8f6a | ||
|   | 6c00c58f2a | ||
|   | 4931fbce49 | ||
|   | fefc7ea600 | ||
|   | d220389647 | ||
|   | a1f910c159 | ||
|   | e4866563de | ||
|   | 47f45aa229 | ||
|   | affe334675 | ||
|   | ee7e184e26 | ||
|   | bec0ebacf1 | ||
|   | 5bd6d631c6 | ||
|   | fd1799f3bb | ||
|   | d84a0c51e0 | ||
|   | d9a7c7de51 | ||
|   | d57e09889a | ||
|   | eecb86bfb0 | ||
|   | 0b1197936c | ||
|   | b545ac6391 | ||
|   | a922132e4a | ||
|   | 9474e8d6d2 | ||
|   | 6328428568 | ||
|   | ea9a88a9b8 | ||
|   | aec7358ca4 | ||
|   | 3c334b2bb6 | ||
|   | 75bba0da92 | ||
|   | c0bfe7be15 | ||
|   | 22ac08e06d | ||
|   | 87037136ef | ||
|   | 2182e37433 | ||
|   | 1de82b220d | ||
|   | bd878756fc | ||
|   | 8d7f402efb | ||
|   | d3299beec7 | ||
|   | f9192db358 | ||
|   | c69c0c0446 | ||
|   | deb2911c0e | ||
|   | e31a306a38 | ||
|   | d9a7773011 | ||
|   | 2b14916813 | ||
|   | 1d1530e14c | ||
|   | b4fdc025a8 | ||
|   | f1c14fe0b4 | ||
|   | 38306cda54 | ||
|   | 5a0f0023cf | ||
|   | 6dcdb8b821 | ||
|   | 781f52a287 | ||
|   | f75ff58b4b | ||
|   | ae9bf16dee | ||
|   | 17a8bf212f | ||
|   | 4fc76afef4 | ||
|   | a31155a72a | ||
|   | 75601f7924 | ||
|   | 8b6314ccfb | ||
|   | 6de7dc5879 | ||
|   | 6aaee5f23b | ||
|   | dd06dcebe1 | ||
|   | b35c26b751 | ||
|   | 128f341635 | ||
|   | e48bc1be48 | ||
|   | 0077b9c0a2 | ||
|   | fe37fb5921 | ||
|   | 221ecd0a30 | ||
|   | 560492707d | ||
|   | dfdf4916fa | ||
|   | 97a8c98886 | ||
|   | 62fb70e9d1 | ||
|   | 8a9098a36c | ||
|   | 28027c2aa2 | ||
|   | d60029d66e | ||
|   | 226fe8bdf9 | ||
|   | 33237b4502 | ||
|   | af6c394785 | ||
|   | 558d12d7f6 | ||
|   | bfa8a6da26 | ||
|   | aa6b3d22a2 | ||
|   | 2eb355733f | ||
|   | e66cdacb93 | ||
|   | c67f2da283 | ||
|   | e192261788 | ||
|   | c63ca99c1c | ||
|   | 1c99c4ad11 | ||
|   | bbcfc10677 | ||
|   | 47e67eab26 | ||
|   | 650b95045d | ||
|   | 5603134e58 | ||
|   | d12fd897cb | ||
|   | 5e95203a5d | ||
|   | cad4a571ce | ||
|   | 139ab3740a | ||
|   | 7b832e1745 | ||
|   | 914b9e441b | ||
|   | f0f6ab49f5 | ||
|   | 436d147925 | ||
|   | 4bd78a7df4 | ||
|   | 7ee6a9dc25 | ||
|   | 1b56ae8478 | ||
|   | d52c0b6f05 | ||
|   | 3ff2bfa0e4 | ||
|   | aa21a3d5c3 | ||
|   | fc33ad8cf2 | ||
|   | 779043f7a3 | ||
|   | 265bb99382 | ||
|   | 7493db2338 | ||
|   | c3ad019c99 | ||
|   | 05b84bfe91 | ||
|   | dbfa1e55b6 | ||
|   | a0fd63f611 | ||
|   | 4ec0401529 | ||
|   | 61e6554b7f | ||
|   | f6f3f79aa8 | ||
|   | c16c017f8b | ||
|   | 2f03ef39d1 | ||
|   | db33926432 | ||
|   | 946090b9cd | ||
|   | 1f7f0fda71 | ||
|   | b84d947be4 | ||
|   | 07c67138c9 | ||
|   | 10717bd39b | ||
|   | 302bb4a4b3 | ||
|   | 81b5af2d1b | ||
|   | 87c562845c | ||
|   | 6c81d74626 | ||
|   | 533c24a471 | ||
|   | 6a9697387a | ||
|   | 85c8981b3d | ||
|   | 6c5b8e1d59 | ||
|   | 2cc16d89e6 | ||
|   | 42eb74922d | ||
|   | c528a7ee33 | ||
|   | eb2da7ec2b | ||
|   | 01ed950bbe | ||
|   | b1076e0a9e | ||
|   | 332eb7651a | ||
|   | cfdcf5c933 | ||
|   | 820de919b6 | ||
|   | a32cd520bd | ||
|   | b93a60daf9 | ||
|   | e2844f5e04 | ||
|   | cabb46db3d | ||
|   | d09b436937 | ||
|   | 10fdb1d743 | ||
|   | f0d3fccd4b | ||
|   | aff19f64b5 | ||
|   | 15a56b42d6 | ||
|   | d3706814e9 | ||
|   | 6513dcef68 | ||
|   | 81f22465ba | ||
|   | dccc77a325 | ||
|   | 13ac89af24 | ||
|   | ffefcab1bc | ||
|   | 0226b53b75 | ||
|   | bbf80d0f93 | ||
|   | 6003f24f78 | ||
|   | 4382a80b9a | ||
|   | 9fe920cd90 | ||
|   | f0ee7115d3 | ||
|   | 5986c653ef | ||
|   | 0e7203be89 | ||
|   | 52dbc96c32 | ||
|   | 1c8da21083 | ||
|   | 8f304d8167 | ||
|   | 30a0bd9cf5 | ||
|   | ae40cdf92f | ||
|   | b342fbdcda | ||
|   | d1ea596f88 | ||
|   | 064cf971ef | ||
|   | 91b1598756 | ||
|   | 17b18bca3c | ||
|   | be3d601217 | ||
|   | ca0fd33d2d | ||
|   | 271f96f78f | ||
|   | b0130e6b3b | ||
|   | d0c1f3e25b | ||
|   | b244710ddb | ||
|   | d465291ded | ||
|   | 84e462d5f6 | ||
|   | 508466a175 | ||
|   | e6dd4a6456 | ||
|   | 8d62e21072 | ||
|   | 25fe47f262 | ||
|   | fe8365d214 | ||
|   | 2519a8cc9f | ||
|   | b8ff21124a | ||
|   | 6aafc2dfd2 | ||
|   | 65b22480f4 | ||
|   | 60f19269d0 | ||
|   | 5121499082 | ||
|   | 3e049a90b7 | ||
|   | c5d97df7f1 | ||
|   | c2479ccb7a | ||
|   | fc07eb45f4 | ||
|   | c7cdb0f266 | ||
|   | 92aedf850e | ||
|   | dd157fc349 | ||
|   | 05f3ca880f | ||
|   | a18d41a463 | ||
|   | 1affbff8f9 | ||
|   | c55d0bb804 | ||
|   | 0ffec712e1 | ||
|   | 6ebac3dc76 | ||
|   | 3b976ea9f1 | ||
|   | 2c16dfb526 | ||
|   | fe3a78ab19 | ||
|   | 1a984ea847 | ||
|   | 2a0cde3041 | ||
|   | 3552775b52 | ||
|   | 818a632e80 | ||
|   | 00afb0f638 | ||
|   | 2e32d415c0 | ||
|   | 3dfc509d33 | ||
|   | 4379142af7 | ||
|   | 8a6dc57212 | ||
|   | af636c535c | ||
|   | 2f77b0a4c6 | ||
|   | 08ad385e0e | ||
|   | 5623e0bb0e | ||
|   | 3d438d8d64 | ||
|   | d89c495782 | ||
|   | f5ba174f4d | 
							
								
								
									
										618
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										618
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -6,6 +6,620 @@ | |||||||
|  |  | ||||||
|                                History of Changes |                                History of Changes | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Daniel (20 February 2002) | ||||||
|  | - Andr<64>s Garc<72>a provided a solution to bug report #515228. the total time | ||||||
|  |   counter was not set correctly when -I was used during some conditions (all | ||||||
|  |   headers were read in one single read). | ||||||
|  |  | ||||||
|  | - Nico Baggus provided a huge patch with minor tweaks all over to make curl | ||||||
|  |   compile nicely on VMS. | ||||||
|  |  | ||||||
|  | Daniel (19 February 2002) | ||||||
|  | - Rick Richardson found out that by replacing PF_UNSPEC with PF_INET in the | ||||||
|  |   getaddrinfo() calls, he could speed up some name resolving calls with an | ||||||
|  |   order of magnitudes on his Redhat Linux 7.2. | ||||||
|  |  | ||||||
|  | - Philip Gladstone found a second INADDR_NONE problem where we used long | ||||||
|  |   intead of in_addr_t which caused 64bit problemos. We really shouldn't define | ||||||
|  |   that on two different places. | ||||||
|  |  | ||||||
|  | Daniel (18 February 2002) | ||||||
|  | - Philip Gladstone found a problem in how HTTP requests were sent if the | ||||||
|  |   request couldn't be sent all at once. | ||||||
|  |  | ||||||
|  | - Emil found and corrected a bad connection timeout comparison that made curl | ||||||
|  |   use the longest of connect-timeout and timout as a timeout value, instead of | ||||||
|  |   the shortest as it was supposed to! | ||||||
|  |  | ||||||
|  | - Aron Roberts provided updated information about LDAP URL syntax to go into | ||||||
|  |   the manual as a replacement for the old references. | ||||||
|  |  | ||||||
|  | Daniel (17 February 2002) | ||||||
|  | - Philip Gladstone pointed out two missing include files that made curl core | ||||||
|  |   dump on 64bit architectures. We need to pay more attention on these details. | ||||||
|  |   It is *lethal* to for example forget the malloc() prototype, as 'int' is | ||||||
|  |   32bit and malloc() must return a 64bit pointer on these platforms. | ||||||
|  |  | ||||||
|  | - Giaslas Georgios fixed a problem with Host: headers on repeated requests on | ||||||
|  |   the same handle using a proxy. | ||||||
|  |  | ||||||
|  | Daniel (8 February 2002) | ||||||
|  | - Hanno L. Kranzhoff accurately found out that disabling the Expect: header | ||||||
|  |   when doing multipart formposts didn't work very well. It disabled other | ||||||
|  |   parts of the request header too, resulting in a broken header. When I fixed | ||||||
|  |   this, I also noticed that the Content-Type wasn't possible to disable. It is | ||||||
|  |   now, even though it probably is really stupid to try to do this (because of | ||||||
|  |   the boundary string that is included in the internally generated header, | ||||||
|  |   used as form part separator.) | ||||||
|  |  | ||||||
|  | Daniel (7 February 2002) | ||||||
|  | - I moved the config*.h files from the root directory to the lib/ directory. | ||||||
|  |  | ||||||
|  | - I've added the new test suite HTTP server to the CVS repository, It seems to | ||||||
|  |   work pretty good now, but we must make it get used by the test scripts | ||||||
|  |   properly and then we need to make sure that it compiles, builds and runs on | ||||||
|  |   most operating systems. | ||||||
|  |  | ||||||
|  | Version 7.9.5-pre1 | ||||||
|  |  | ||||||
|  | Daniel (6 February 2002) | ||||||
|  | - Miklos Nemeth provided updated windows makefiles and INSTALL docs. | ||||||
|  |  | ||||||
|  | - Mr Larry Fahnoe found a problem with formposts and I managed to track down | ||||||
|  |   and patch this bug. This was actually two bugs, as the posted size was also | ||||||
|  |   said to be two bytes too large. | ||||||
|  |  | ||||||
|  | - Brent Beardsley found out and brought a correction for the | ||||||
|  |   CURLINFO_CONTENT_TYPE parser that was off one byte. This was my fault, I | ||||||
|  |   accidentaly broke Giaslas Georgios' patch. | ||||||
|  |  | ||||||
|  | Daniel (5 February 2002) | ||||||
|  | - Kevin Roth found yet another SSL download problem. | ||||||
|  |  | ||||||
|  | Version 7.9.4 | ||||||
|  |  | ||||||
|  | - no changes since pre-release | ||||||
|  |  | ||||||
|  | Version 7.9.4-pre2 | ||||||
|  |  | ||||||
|  | Daniel (3 February 2002) | ||||||
|  | - Eric Melville provided a few spelling corrections in the curl man page. | ||||||
|  |  | ||||||
|  | Daniel (1 February 2002) | ||||||
|  | - Andreas Damm corrected the unconditional use of gmtime() in getdate, it now | ||||||
|  |   uses gmtime_r() on all hosts that have it. | ||||||
|  |  | ||||||
|  | Daniel (31 January 2002) | ||||||
|  | - An anonymous bug report identified a problem in the DNS caching which made it | ||||||
|  |   sometimes allocate one byte too little to store the cache entry in. This | ||||||
|  |   happened when the port number started with 1! | ||||||
|  |  | ||||||
|  | - Albert Chin provided a patch that improves the gethostbyname_r() configure | ||||||
|  |   check on HP-UX 11.00. | ||||||
|  |  | ||||||
|  | Version 7.9.4-pre1 | ||||||
|  |  | ||||||
|  | Daniel (30 January 2002) | ||||||
|  | - Georg Horn found another way the SSL reading failed due to the non-blocking | ||||||
|  |   state of the sockets! I fixed. | ||||||
|  |  | ||||||
|  | Daniel (29 January 2002) | ||||||
|  | - Multipart formposts now send the full request properly, including the CRLF. | ||||||
|  |   They were previously treated as part of the post data. | ||||||
|  |  | ||||||
|  | - The upload byte counter bugged. | ||||||
|  |  | ||||||
|  | - T. Bharath pointed out that we seed SSL on every connect, which is a time- | ||||||
|  |   consuming operation that should only be needed to do once. We patched | ||||||
|  |   libcurl to now only seed on the first connect when unseeded. The seeded | ||||||
|  |   status is global so it'll now only happen once during a program's life time. | ||||||
|  |  | ||||||
|  |   If the random_file or egdsocket is set, the seed will be re-made though. | ||||||
|  |  | ||||||
|  | - Giaslas Georgios introduced CURLINFO_CONTENT_TYPE that lets | ||||||
|  |   curl_easy_getinfo() read the content-type from the previous request. | ||||||
|  |  | ||||||
|  | Daniel (28 January 2002) | ||||||
|  | - Kjetil Jacobsen found a way to crash curl and after much debugging, it | ||||||
|  |   turned out it was a IPv4-linux only problem introduced in 7.9.3 related to | ||||||
|  |   name resolving. | ||||||
|  |  | ||||||
|  | - Andreas Damm posted a huge patch that made the curl_getdate() function fully | ||||||
|  |   reentrant! | ||||||
|  |  | ||||||
|  | - Steve Marx pointed out that you couldn't mix CURLOPT_CUSTOMREQUEST with | ||||||
|  |   CURLOPT_POSTFIELDS. You can now! | ||||||
|  |  | ||||||
|  | Daniel (25 January 2002) | ||||||
|  | - Krishnendu Majumdar pointed out that the header length counter was not reset | ||||||
|  |   between multiple requests on the same handle. | ||||||
|  |  | ||||||
|  | - Pedro Neves rightfully questioned why curl always append \r\n to the data | ||||||
|  |   that is sent in HTTP POST requests. Unfortunately, this broke the test suite | ||||||
|  |   as the test HTTP server is lame enough not to deal with this... :-O | ||||||
|  |  | ||||||
|  | - Following Location: headers when the connection didn't close didn't work as | ||||||
|  |   libcurl didn't properly stop reading. This problem was added in 7.9.3 due to | ||||||
|  |   the restructured internals. 'Frank' posted a bug report about this. | ||||||
|  |  | ||||||
|  | Daniel (24 January 2002) | ||||||
|  | - Kevin Roth very quickly spotted that we wrongly installed the example | ||||||
|  |   programs that were built in the multi directory, when 'make install' was | ||||||
|  |   used. :-/ | ||||||
|  |  | ||||||
|  | Version 7.9.3 | ||||||
|  |  | ||||||
|  | Daniel (23 January 2002) | ||||||
|  | - Andr<64>s Garc<72>a found a persistancy problem when doing HTTP HEAD, that made | ||||||
|  |   curl "hang" until the connection was closed by the server. This problem has | ||||||
|  |   been introduced in 7.9.3 due to internal rewrites, this was not present in | ||||||
|  |   7.9.2. | ||||||
|  |  | ||||||
|  | Version 7.9.3-pre4 | ||||||
|  |  | ||||||
|  | Daniel (19 January 2002) | ||||||
|  | - Antonio filed bug report #505514 and provided a fix! When doing multipart | ||||||
|  |   formposts, libcurl would include an error text in the actual post if a | ||||||
|  |   specified file wasn't found. This is not libcurl's job. Instead we add an | ||||||
|  |   empty part. | ||||||
|  |  | ||||||
|  | Daniel (18 January 2002) | ||||||
|  | - Played around with stricter compiler warnings for gcc (when ./configure | ||||||
|  |   --enable-debug is used) and changed some minor things to stop the warnings. | ||||||
|  |  | ||||||
|  | - Commented out the 'long long' and 'long double' checks in configure.in, as | ||||||
|  |   we don't currently use them anyway and the code in lib/mprintf.c that use | ||||||
|  |   them causes warnings. | ||||||
|  |  | ||||||
|  | - Saul Good and jonatan pointed out Mac OS X build problems with pre3 and how | ||||||
|  |   to correct them. Two compiler warnings were removed as well. | ||||||
|  |  | ||||||
|  | - Andr<64>s Garc<72>a fixed two minor mingw32 building problems. | ||||||
|  |  | ||||||
|  | Version 7.9.3-pre3 | ||||||
|  |  | ||||||
|  | Daniel (17 January 2002) | ||||||
|  | - docs/libcurl-the-guide is a new tutorial for our libcurl programming | ||||||
|  |   friends. | ||||||
|  |  | ||||||
|  | - Richard Archer brought back the ability to compile and build with OpenSSL | ||||||
|  |   versions before 0.9.5. | ||||||
|  |   [http://sourceforge.net/tracker/?func=detail&atid=100976&aid=504163&group_id=976] | ||||||
|  |  | ||||||
|  | - The DNS cache code didn't take the port number into account, which made it | ||||||
|  |   work rather bad on IPv6-enabled hosts (especially when doing passive | ||||||
|  |   FTP). Sterling fixed it. | ||||||
|  |  | ||||||
|  | Daniel (16 January 2002) | ||||||
|  | - Georg Horn could make a transfer time-out without error text. I found it and | ||||||
|  |   corrected it. | ||||||
|  |  | ||||||
|  | - SSL writes didn't work, they return an uninitialized value that caused | ||||||
|  |   havoc all over. Georg Horn experienced this. | ||||||
|  |  | ||||||
|  | - Kevin Roth patched the curl_version() function to use the proper OpenSSL | ||||||
|  |   function for version information. This way, curl will report the version of | ||||||
|  |   the SSL library actually running right now, not the one that had its headers | ||||||
|  |   installed when libcurl was built. Mainly intersting when running with shared | ||||||
|  |   OpenSSL libraries.   | ||||||
|  |  | ||||||
|  | Version 7.9.3-pre2 | ||||||
|  |  | ||||||
|  | Daniel (16 January 2002) | ||||||
|  | - Mofied the main transfer loop and related stuff to deal with non-blocking | ||||||
|  |   sockets in the upload section. While doing this, I've now separated the | ||||||
|  |   connection oriented buffers to have one for downloads and one for uploads | ||||||
|  |   (as two can happen simultaneously). I also shrunk the buffers to 20K | ||||||
|  |   each. As we have a scratch buffer twice the size of the upload buffer, we | ||||||
|  |   arrived at 80K for buffers compared with the previous 150K. | ||||||
|  |  | ||||||
|  | - Added the --cc option to curl-config command as it enables so very cool | ||||||
|  |   one-liners. Have a go a this one, building the simple.c example: | ||||||
|  |  | ||||||
|  |         $ `curl-config --cc --cflags --libs` -o example simple.c | ||||||
|  |  | ||||||
|  | Daniel (14 January 2002) | ||||||
|  | - I made all socket reads (recv) handle EWOULDBLOCK. I hope nicely. Now we | ||||||
|  |   only need to address all writes (send) too and then I'm ready for another | ||||||
|  |   pre-release... | ||||||
|  |  | ||||||
|  | - Stoned Elipot patched the in_addr_t configure test to make it work better on | ||||||
|  |   more platforms. | ||||||
|  |  | ||||||
|  | Daniel (9 January 2002) | ||||||
|  | - Cris Bailiff found out that filling up curl's SSL session cache caused a | ||||||
|  |   crash! | ||||||
|  |  | ||||||
|  | - Posted the curl questionnaire on the web site. If you haven't posted your | ||||||
|  |   opinions there yet, go there and do it now while it is still there: | ||||||
|  |  | ||||||
|  |         http://curl.haxx.se/q/ | ||||||
|  |  | ||||||
|  | - Georg Horn quickly found out that the SSL reading no longer worked as | ||||||
|  |   supposed since the switch to non-blocking sockets. I've made a quick patch | ||||||
|  |   (for reading only) but we should improve it even further. | ||||||
|  |  | ||||||
|  | Version 7.9.3-pre1 | ||||||
|  |  | ||||||
|  | Daniel (7 January 2002) | ||||||
|  | - I made the 'bool' typedef use an "unsigned char". It makes it the same on | ||||||
|  |   all platforms, no matter what the platform thinks the default format for | ||||||
|  |   char is. This was noticed since we made a silly comparison involving such a | ||||||
|  |   bool variable, and only one compiler/platform combination (on Debian Linux) | ||||||
|  |   complained about it (that happened to have its char unsigned by default). | ||||||
|  |  | ||||||
|  | - Bug report #495290 identified a cookie parsing problem that was corrected. | ||||||
|  |   When a Set-Cookie: line is received without a trailing semicolon, libcurl | ||||||
|  |   didn't read the last "name=value" pair of the line, leading to confusions... | ||||||
|  |  | ||||||
|  | - Sterling committed his updated DNS cache code. | ||||||
|  |  | ||||||
|  | - I worked with Georg Horn and comments from G<>tz Babin-Ebell and switched | ||||||
|  |   curl's socket operations completely over to non-blocking for the entire | ||||||
|  |   operation (previously we used non-blocking only for the connection phase). | ||||||
|  |   We had to do this to make the SSL connection phase timeout properly without | ||||||
|  |   the use of signals. A little extra code to deal with this was added. | ||||||
|  |  | ||||||
|  | - T. Bharath pointed out a slightly obscure cookie engine flaw. | ||||||
|  |  | ||||||
|  | - Pete Su pointed out that libcurl didn't treat HTTP code 204 as it should. | ||||||
|  |   204-replies never provides a response-body. This resulted in bad persistant | ||||||
|  |   behavior when 204 was received. | ||||||
|  |  | ||||||
|  | Daniel (5 January 2002) | ||||||
|  | - SM updated the VC++ library Makefiles for the new source files. | ||||||
|  |  | ||||||
|  | Daniel (4 January 2002) | ||||||
|  | - I discovered that we wrongly used inet_ntoa() (instead of inet_ntoa_r() in | ||||||
|  |   two places in the source code). One happened with VERBOSE set on connects, | ||||||
|  |   and the other when VERBOSE was on and krb4 over nat was used... I honestly | ||||||
|  |   don't think anyone has suffered from these mistakes. | ||||||
|  |  | ||||||
|  | - I replaced a lot of silly occurances of printf() to instead use the more | ||||||
|  |   appropriate Curl_infof() or Curl_failf(). The krb4 and telnet code were | ||||||
|  |   affected. | ||||||
|  |  | ||||||
|  | - Philip Gladstone found a few more problems with 64-bit archs (the 64-bit | ||||||
|  |   sparc on solaris 8). | ||||||
|  |  | ||||||
|  | - After discussions on the libcurl list with Raoul Cridlig, I just made FTP | ||||||
|  |   response lines get passed to the header callback if such a one is | ||||||
|  |   registered. It'll make it possible for any application to get all the | ||||||
|  |   responses an FTP server sends to libcurl. | ||||||
|  |  | ||||||
|  | Daniel (3 January 2002) | ||||||
|  | - Sterling Hughes brought a few buckets of code. Now, libcurl will | ||||||
|  |   automatically cache DNS lookups and re-use the previous results first if any | ||||||
|  |   such is available. It greatly improves speed when doing many repeated | ||||||
|  |   operations to the same host. | ||||||
|  |  | ||||||
|  | - As the test case uses --include and then --head, I had to modify src/main.c | ||||||
|  |   to deal with this situation slightly better than previously. When done, we | ||||||
|  |   have 100% good tests again in the main branch. | ||||||
|  |  | ||||||
|  | Daniel (2 January 2002) | ||||||
|  | - Made test case 25 run again in the multi-dev branch. But it seems that the | ||||||
|  |   changes done on dec-20 made test case 104 cease to work (in both branches). | ||||||
|  |  | ||||||
|  | - Philip Gladstone pointed out a few portability problems in the source code | ||||||
|  |   that didn't compile on 64-bit sparcs using Sun's native compiler... | ||||||
|  |  | ||||||
|  | Daniel (20 December 2001) | ||||||
|  | - Bj<42>rn Stenberg caught an unpleasent (but hard-to-find) bug that could cause | ||||||
|  |   libcurl to hang on transfers over proxy, when the proxy was specified with | ||||||
|  |   an environment variable! | ||||||
|  |  | ||||||
|  | - Added code to make ftp operations treat the NO_BODY and HEADERS options | ||||||
|  |   better: | ||||||
|  |  | ||||||
|  |    NO_BODY set TRUE and HEADERS set TRUE: | ||||||
|  |     Return a set of headers with file info | ||||||
|  |  | ||||||
|  |    NO_BODY set FALSE | ||||||
|  |     Transfer data as usual, HEADERS is ignored | ||||||
|  |  | ||||||
|  |    NO_BODY set TRUE and HEADERS set FALSE | ||||||
|  |     Don't transfer any data, don't return any headers. Just perform the set | ||||||
|  |     of FTP commands. | ||||||
|  |  | ||||||
|  | Daniel (17 December 2001) | ||||||
|  | - G<>tz Babin-Ebell dove into the dark dungeons of the OpenSSL ENGINE stuff and | ||||||
|  |   made libcurl support it! This allows libcurl to do SSL connections with the | ||||||
|  |   private key stored in external hardware. | ||||||
|  |  | ||||||
|  |   To make this good, he had to add a bunch of new library options that'll be | ||||||
|  |   useful to others as well: | ||||||
|  |  | ||||||
|  |    CURLOPT_SSLCERTTYPE  set SSL cert type (PEM/DER) | ||||||
|  |    CURLOPT_SSLKEY       set SSL private key (file) | ||||||
|  |    CURLOPT_SSLKEYTYPE:  set SSL key type (PEM/DER/ENG) | ||||||
|  |    CURLOPT_SSLKEYPASSWD: set the passphrase for your private key | ||||||
|  |                           (CURLOPT_SSLCERTPASSWD is an alias) | ||||||
|  |    CURLOPT_SSLENGINE:   set the name of the crypto engine | ||||||
|  |                         (returns CURLE_SSL_ENGINE_NOTFOUND on error) | ||||||
|  |    CURLOPT_SSLENGINE_DEFAULT: set the default engine | ||||||
|  |  | ||||||
|  |   There are two new failure codes: | ||||||
|  |  | ||||||
|  |    CURLE_SSL_ENGINE_NOTFOUND | ||||||
|  |    CURLE_SSL_ENGINE_SETFAILED | ||||||
|  |  | ||||||
|  | Daniel (14 December 2001) | ||||||
|  | - We have "branched" the source-tree at a few places. Checkout the CVS sources | ||||||
|  |   with the 'multi-dev' label to get the latest multi interface development | ||||||
|  |   tree. The idea is to only branch affected files and to restrict the branch | ||||||
|  |   to the v8 multi interface development only. | ||||||
|  |  | ||||||
|  |   *NOTE* that if we get bug reports and patches etc, we might need to apply | ||||||
|  |   them in both branches! | ||||||
|  |  | ||||||
|  |   The multi-dev branch is what we are gonna use as main branch in the future | ||||||
|  |   if it turns out successful. Thus, we must maintain both now in case we need | ||||||
|  |   them. The current main branch will be used if we want to release a 7.9.3 or | ||||||
|  |   perhaps a 7.10 release before version 8. Which is very likely. | ||||||
|  |  | ||||||
|  | - Marcus Webster provided code for the new CURLFORM_CONTENTHEADER option for | ||||||
|  |   curl_formadd(), that lets an application add a set of headers for that | ||||||
|  |   particular part in a multipart/form-post. He also provided a section to the | ||||||
|  |   man page that describes the new option. | ||||||
|  |  | ||||||
|  | Daniel (11 December 2001) | ||||||
|  | - Ben Greear made me aware of the fact that the Curl_failf() usage internally | ||||||
|  |   was a bit sloppy with adding newlines or not to the error messages. Let's | ||||||
|  |   once and for all say that they do not belong there! | ||||||
|  |  | ||||||
|  | - When uploading files with -T to give a local file name, and you end the URL | ||||||
|  |   with a slash to have the local file name used remote too, we now no longer | ||||||
|  |   use the local directory as well. Only the file part of the -T file name | ||||||
|  |   will be appended to the right of the slash in the URL. | ||||||
|  |  | ||||||
|  | Daniel (7 December 2001) | ||||||
|  | - Michal Bonino pointed out that Digital Unix doesn't have gmtime_r so the | ||||||
|  |   link failed. Added a configure check and corrected source code. | ||||||
|  |  | ||||||
|  | Version 7.9.2 | ||||||
|  |  | ||||||
|  | Daniel (5 December 2001) | ||||||
|  | - Jon Travis found out that if you used libcurl and CURLOPT_UPLOAD and then | ||||||
|  |   on the same handle used CURLOPT_HTTPGET it would still attempt to upload. | ||||||
|  |   His suggested fix was perfect. | ||||||
|  |  | ||||||
|  | Daniel (4 December 2001) | ||||||
|  | - Incorporated more macos fixes and added four specific files in a new | ||||||
|  |   subdirectory below src. | ||||||
|  |  | ||||||
|  | Daniel (3 December 2001) | ||||||
|  | - Eric Lavigne reported two problems: | ||||||
|  |  | ||||||
|  |   First one in the curl_strnequal() function. I think this problem is rather | ||||||
|  |   macos 9 specific, as most platform provides a function to use instead of the | ||||||
|  |   one provided by libcurl. | ||||||
|  |  | ||||||
|  |   A second, more important, was in the way we take care of FTP responses. The | ||||||
|  |   code would read a large chunk of data and search for the end-of-response | ||||||
|  |   line within that chunk. When found, it would just skip the rest of the | ||||||
|  |   data. However, when the network connections are special, or perhaps the | ||||||
|  |   server is, we could actually get more than one response in that chunk of | ||||||
|  |   data so that when the next invoke to this function was done, the response | ||||||
|  |   had already been read and thrown away. Now, we cache the data not used in | ||||||
|  |   one call, as it could be useful in the subsequent call. Test case 126 was | ||||||
|  |   added and the test ftp server modified, to exercise this particular case. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre8 | ||||||
|  |  | ||||||
|  | Daniel (2 December 2001) | ||||||
|  | - Bug report #487825 correctly identified a problem when using a proxy and | ||||||
|  |   following a redirection from HTTP to HTTPS. libcurl then re-used the same | ||||||
|  |   proxy connection but without doing a proper HTTPS request. | ||||||
|  |  | ||||||
|  | - Fixed win32 compiling quirks. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre7 | ||||||
|  |  | ||||||
|  | Daniel (30 November 2001) | ||||||
|  | - Documented --disable-epsv and CURLOPT_FTP_USE_EPSV. | ||||||
|  |  | ||||||
|  | Daniel (29 November 2001) | ||||||
|  | - Added --disable-epsv as an option. When used, curl won't attempt to use the | ||||||
|  |   EPSV command when doing passive FTP downloads. Wrote a test case for it. | ||||||
|  |  | ||||||
|  | - Eric provided a few more fixes for building on Macs. He also pointed out | ||||||
|  |   a flaw in the signal handler restoration code. | ||||||
|  |  | ||||||
|  | Daniel (28 November 2001) | ||||||
|  | - Fiddled with some Tru64 problems reported by Dimitris Sarris. They appeared | ||||||
|  |   only when using VERBOSE ftp transfers. Do we use a too small buffer for | ||||||
|  |   gethostbyaddr_r(), was the lack of using in_addr_t wrong or is it that the | ||||||
|  |   hostent struct must be blanked before use? With Dimitris help and these | ||||||
|  |   patches, the problems seem to be history. | ||||||
|  |  | ||||||
|  | - CURLOPT_FTP_USE_EPSV was added and can be set to FALSE to prevent libcurl | ||||||
|  |   from using the EPSV command before trying the normal PASV. Heikki Korpela | ||||||
|  |   pointed out that some firewalls and similar don't like the EPSV so we must | ||||||
|  |   be able to shut if off to work everywhere. | ||||||
|  |  | ||||||
|  | - I added a configure check for 'in_addr_t' and made the ftp code use that to | ||||||
|  |   receive the inet_addr() return code in. Works on Solaris and Linux at | ||||||
|  |   least. The Linux man page for inet_addr() doesn't even mention in_addr_t... | ||||||
|  |  | ||||||
|  | - Adjusted (almost) all FTP tests to the new command sequence. | ||||||
|  |  | ||||||
|  | - FTP command sequence changes: | ||||||
|  |  | ||||||
|  |   EPSV is now always attempted before PASV. It is the final touch to make IPv6 | ||||||
|  |   passive FTP downloads to work, but EPSV is not restricted to IPv6 but works | ||||||
|  |   fine with IPv4 too on the servers that support it. | ||||||
|  |  | ||||||
|  |   SIZE is now always issued before RETR. It makes curl know the actual | ||||||
|  |   download size before the download takes place, as it makes it less important | ||||||
|  |   to find the size sent in RETR responses. Many sites don't include the size | ||||||
|  |   in there. | ||||||
|  |  | ||||||
|  |   Both these changes made it necessary to change the test suite's ftp server | ||||||
|  |   code, and all FTP test cases need to be checked and adjusted! | ||||||
|  |  | ||||||
|  | Daniel (27 November 2001) | ||||||
|  | - Hans Steegers pointed out that the telnet code read from stdout, not stdin | ||||||
|  |   as it is supposed to do! | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre6 | ||||||
|  |  | ||||||
|  | Daniel (27 November 2001) | ||||||
|  | - Eric Lavigne's minor changes to build on MacOS before OS X were applied. | ||||||
|  |  | ||||||
|  | - greep at mindspring.com provided a main index.html page for our release | ||||||
|  |   archive docs directory. It just links to all the existing HTML files, but | ||||||
|  |   I think it may come useful to people. | ||||||
|  |  | ||||||
|  | - There's now some initial code to support the EPSV FTP command. That should | ||||||
|  |   be used to do passive transfers IPv6-style. The code is still #if 0'ed in | ||||||
|  |   lib/ftp.c as I have no IPv6 ftp server to test this with. | ||||||
|  |  | ||||||
|  | Daniel (26 November 2001) | ||||||
|  | - Robert Schlabbach had problems to understand how to do resumed transfers, | ||||||
|  |   and I clarified the man page -C section somewhat. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre5 | ||||||
|  |  | ||||||
|  | Daniel (22 November 2001) | ||||||
|  | - Andr<64>s Garc<72>a helped me out to track down the roots of bug report #479537, | ||||||
|  |   which was concerning curl returning the wrong error code when failing to | ||||||
|  |   connect. This didn't happen on all systems, and more specificly I've so far | ||||||
|  |   only seen this happen on IPv4-only Linux hosts. | ||||||
|  |  | ||||||
|  | - I applied the fixes for the two bugs Eric Lavigne found when doing his MacOS | ||||||
|  |   port. A missing comma in arpa_telnet.h and a pretty wild write in the FTP | ||||||
|  |   response reader function. The latter write is however likely to occur in our | ||||||
|  |   own buffer unless very big FTP server replies (>25K) are read. I've never | ||||||
|  |   seen such a reply ever, so I think this is a relatively minor risk. | ||||||
|  |  | ||||||
|  | Daniel (21 November 2001) | ||||||
|  | - Moonesamy provided code to prevent junk from being output when libcurl | ||||||
|  |   returns an error code but no error description and that corrects how make is | ||||||
|  |   run in the Makefile.dist file (that appears as root Makefile in release | ||||||
|  |   archives). | ||||||
|  |  | ||||||
|  | - Eric Lavigne mailed me bugfixes and patches for building libcurl on MacOS | ||||||
|  |   (non-X). | ||||||
|  |  | ||||||
|  | - Kevin Roth modified the cygwin files once again, now to build against the | ||||||
|  |   shared OpenSSL DLLs. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre4 | ||||||
|  |  | ||||||
|  | Daniel (20 November 2001) | ||||||
|  | - Georg Horn brought a patch that introduced CURLINFO_STARTTRANSFER_TIME, | ||||||
|  |   complete with man page updates! | ||||||
|  |  | ||||||
|  | Daniel (19 November 2001) | ||||||
|  | - Miklos Nemeth provided details enough to update the Borland makefile | ||||||
|  |   properly. | ||||||
|  |  | ||||||
|  | - Lars M Gustafsson found a case with a bad free(). In fact, it was so bad I'm | ||||||
|  |   amazed we never saw this before! | ||||||
|  |  | ||||||
|  | - Kevin Roth patched the cygwin Makfile. | ||||||
|  |  | ||||||
|  | Daniel (16 November 2001) | ||||||
|  | - Klevtsov Vadim fixed a bug in how time-conditionals were sent when doing | ||||||
|  |   HTTP. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre3 | ||||||
|  |  | ||||||
|  | Daniel (14 November 2001) | ||||||
|  | - Samuel Listopad patched away the problem with SSL we got when someone call | ||||||
|  |   curl_global_init() => curl_global_cleanup() => curl_global_init(). The | ||||||
|  |   second init would not "take" and SSL would be unusable with curl from that | ||||||
|  |   point. This doesn't change the fact that calling the functions that way is | ||||||
|  |   wrong. curl_global_init() should be called exactly once and not more. | ||||||
|  |  | ||||||
|  | Daniel (13 November 2001) | ||||||
|  | - Fixed some minor variable type mixups in ftp.c that caused compiler warnings | ||||||
|  |   on HP-UX 11.00. | ||||||
|  |  | ||||||
|  | - The FTP fix I did yesterday used an uninitialized variable that caused | ||||||
|  |   spurious errors when doing FTP. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre2 | ||||||
|  |  | ||||||
|  | Daniel (12 November 2001) | ||||||
|  | - Ricardo Cadime fell over a multiple-requests problem when first a FTP | ||||||
|  |   directory fetch failed and then a second request is made after that. The | ||||||
|  |   second request happened to get the FTP server response back from the | ||||||
|  |   previous request, when it did its initial CWD command. | ||||||
|  |  | ||||||
|  | - Bjorn Reese pointed out that we could improve the time diff function to | ||||||
|  |   prevent truncation a bit. | ||||||
|  |  | ||||||
|  | - Kai-Uwe Rommel made me aware that -p (http proxy tunnel) silly enough didn't | ||||||
|  |   work for plain HTTP requests! So I made that work. | ||||||
|  |  | ||||||
|  | Version 7.9.2-pre1 | ||||||
|  |  | ||||||
|  | Daniel (12 November 2001) | ||||||
|  | - Rewrote the Curl_ConnectHTTPProxyTunnel(). It should now not only work a lot | ||||||
|  |   faster, it should also support such ("broken") proxies that John Lask | ||||||
|  |   previously have reported problems with. His proxy sends a trailing zero byte | ||||||
|  |   after the end of the (proxy-) headers. I've tested this myself and it seems | ||||||
|  |   to work on a proxy the previous version also worked with...! This rewrite is | ||||||
|  |   due to the problems John Lask previously experienced. | ||||||
|  |  | ||||||
|  | - Andr<64>s Garc<72>a found out why the "current speed" meter sometimes showed 2048K | ||||||
|  |   for very quick transfers. It turned out the "time diff"-function returned a | ||||||
|  |   zero millisecond diff. We now always say it is at least one millisecond! In | ||||||
|  |   reality, these timers very rarely have that good resolution so even though | ||||||
|  |   the time diff was longer than 1 millisecond, it was reported as no diff. | ||||||
|  |  | ||||||
|  | - I also modified the getinfo() again when returning times, as Paul Harrington | ||||||
|  |   reports that 7.9.1 only returns times with 1 second accuracy, which indeed | ||||||
|  |   is wrong. | ||||||
|  |  | ||||||
|  | Daniel (8 November 2001) | ||||||
|  | - Marcus Webster found out that curl_formadd() could read one byte outside a | ||||||
|  |   buffer boundary, which then of course could lead to a crash. Marcus also | ||||||
|  |   gracefully provided a patch for this this. | ||||||
|  |  | ||||||
|  | - Glen Scott ran configure on his Cobalt Qube and it didn't figure out the | ||||||
|  |   correct way of calling gethostbyname_r() and thus failed to resolve hosts. | ||||||
|  |   This is two errors: it shouldn't continue the configure script if it finds | ||||||
|  |   gethostbyname_r() but can't figure out how to use it, and it should really | ||||||
|  |   figure out how to use it as it was running Linux and we know how that | ||||||
|  |   works... | ||||||
|  |   | ||||||
|  | Daniel (7 November 2001) | ||||||
|  | - docs/VERSIONS is a new file in the archive that explains the version number | ||||||
|  |   system we use in the curl project. | ||||||
|  |  | ||||||
|  | - Did some more fixes that now makes libcurl only ignore signals as long as | ||||||
|  |   it needs to, and then restore (if any) previous signal handler again. | ||||||
|  |  | ||||||
|  | Daniel (6 November 2001) | ||||||
|  | - Enrik Berkhan posted bug report #478780, in which he very correctly pointed | ||||||
|  |   out two bad timeout matters in libcurl: we didn't restore the sigaction | ||||||
|  |   struct (the alarm handler for SIGALRM) nor did we restore the previous | ||||||
|  |   alarm() timeout that could've been set by a "parent" process or similar. | ||||||
|  |  | ||||||
|  | - Kevin Roth made the cygwin binary get stripped before install. | ||||||
|  |  | ||||||
|  | Daniel (5 November 2001) | ||||||
|  | - Detlef Schmier reported that curl didn't compile using Solaris 8 with the | ||||||
|  |   native cc compiler. It was due to a bad function prototype. Fixed now. | ||||||
|  |   Unfortunately, I can't enable the -Wstrict-prototypes in my debug builds | ||||||
|  |   though, as gcc then complains like crazy on OpenSSL include files... :-( | ||||||
|  |  | ||||||
|  | - John Lask provided SSL over HTTP proxy fixes. They'll need some tweaking | ||||||
|  |   to work on all platforms. | ||||||
|  |  | ||||||
|  | - John Lask added the -1/--TLSv1 options that forces SSL into using TLS | ||||||
|  |   version 1 when speaking HTTPS. | ||||||
|  |  | ||||||
|  | - John Lask brought a brand new VC++ makefile for the lib directory, that | ||||||
|  |   works a lot better than the previous! | ||||||
|  |  | ||||||
|  | - Ramana Mokkapati brought some clever insights on the LDAP failures (bug | ||||||
|  |   report #475407), and his suggested changes are now applied. | ||||||
|  |  | ||||||
| Version 7.9.1 | Version 7.9.1 | ||||||
|  |  | ||||||
| Daniel (4 November 2001) | Daniel (4 November 2001) | ||||||
| @@ -34,8 +648,8 @@ Daniel (1 November 2001) | |||||||
| Version 7.9.1-pre7 | Version 7.9.1-pre7 | ||||||
|  |  | ||||||
| Daniel (31 October 2001) | Daniel (31 October 2001) | ||||||
| - The curl_easy_getinfo() timers accidentally lost they're subsecond accuracy | - The curl_easy_getinfo() timers accidentally lost their subsecond accuracy as | ||||||
|   as the calculations used longs instead of doubles! Paul Harrington reported. |   the calculations used longs instead of doubles! Paul Harrington reported. | ||||||
|  |  | ||||||
| - The SSL SocketIsDead() checks weren't good enough (as expected really), so I | - The SSL SocketIsDead() checks weren't good enough (as expected really), so I | ||||||
|   had to add a generic internal try-it-out system. If the request on a re-used |   had to add a generic internal try-it-out system. If the request on a re-used | ||||||
|   | |||||||
							
								
								
									
										835
									
								
								CHANGES.0
									
									
									
									
									
								
							
							
						
						
									
										835
									
								
								CHANGES.0
									
									
									
									
									
								
							| @@ -1,838 +1,3 @@ | |||||||
| Daniel (28 December 1999): |  | ||||||
|  - Tim Verhoeven correctly identified that curl |  | ||||||
|    doesn't support URL formatted file names when getting ftp. Now, there's a |  | ||||||
|    problem with getting very weird file names off FTP servers. RFC 959 defines |  | ||||||
|    that the file name syntax to use should be the same as in the native OS of |  | ||||||
|    the server. Since we don't know the peer server system we currently just |  | ||||||
|    translate the URL syntax into plain letters. It is still better and with |  | ||||||
|    the solaris 2.6-supplied ftp server it works with spaces in the file names. |  | ||||||
|  |  | ||||||
| Daniel (27 December 1999): |  | ||||||
|  - When curl parsed cookies straight off a remote site, it corrupted the input |  | ||||||
|    data, which, if the downloaded headers were stored made very odd characters |  | ||||||
|    in the saved data. Correctly identified and reported by Paul Harrington. |  | ||||||
|  |  | ||||||
| Daniel (13 December 1999): |  | ||||||
|  - General cleanups in the library interface. There had been some bad kludges |  | ||||||
|    added during times of stress and I did my best to clean them off. It was |  | ||||||
|    both regarding the lib API as well as include file confusions. |  | ||||||
|  |  | ||||||
| Daniel (3 December 1999): |  | ||||||
|  - A small --stderr bug was reported by Eetu Ojanen... |  | ||||||
|  |  | ||||||
|  - who also brought the suggestion of extending the -X flag to ftp list as |  | ||||||
|    well. So, now it is and the long option is now --request instead. It is |  | ||||||
|    only for ftp list for now (and the former http stuff too of course). |  | ||||||
|  |  | ||||||
| Lars J. Aas (24 November 1999): |  | ||||||
|  - Patched curl to compile and build under BeOS. Doesn't work yet though! |  | ||||||
|  |  | ||||||
|  - Corrected the Makefile.am files to allow putting object files in |  | ||||||
|    different directories than the sources. |  | ||||||
|  |  | ||||||
| Version 6.3.1 |  | ||||||
|  |  | ||||||
| Daniel (23 November 1999): |  | ||||||
|  - I've had this major disk crash. My good old trust-worthy source disk died |  | ||||||
|    along with the machine that hosted it. Thank goodness most of all the |  | ||||||
|    things I've done are either backed up elsewhere or stored in this CVS |  | ||||||
|    server! |  | ||||||
|  |  | ||||||
|  - Michael S. Steuer pointed out a bug in the -F handling |  | ||||||
|    that made curl hang if you posted an empty variable such as '-F name='. It |  | ||||||
|    was one of those old bugs that never have worked properly... |  | ||||||
|  |  | ||||||
|  - Jason Baietto pointed out a general flaw in the HTTP |  | ||||||
|    download. Curl didn't complain if it was prematurely aborted before the |  | ||||||
|    entire download was completed. It does now. |  | ||||||
|  |  | ||||||
| Daniel (19 November 1999): |  | ||||||
|  - Chris Maltby very accurately criticized the lack of |  | ||||||
|    return code checks on the fwrite() calls. I did a thorough check for all |  | ||||||
|    occurrences and corrected this. |  | ||||||
|  |  | ||||||
| Daniel (17 November 1999): |  | ||||||
|  - Paul Harrington pointed out that the -m/--max-time option |  | ||||||
|    doesn't work for the slow system calls like gethostbyname()... I don't have |  | ||||||
|    any good fix yet, just a slightly less bad one that makes curl exit hard |  | ||||||
|    when the timeout is reached. |  | ||||||
|  |  | ||||||
|  - Bjorn Reese helped me point out a possible problem that might be the reason |  | ||||||
|    why Thomas Hurst experience problems in his Amiga version. |  | ||||||
|  |  | ||||||
|  Daniel (12 November 1999): |  | ||||||
|  - I found a crash in the new cookie file parser. It crashed when you gave |  | ||||||
|    a plain http header file as input... |  | ||||||
|  |  | ||||||
| Version 6.3 |  | ||||||
|  |  | ||||||
|  Daniel (10 November 1999): |  | ||||||
|  - I kind of found out that the HTTP time-conditional GETs (-z) aren't always |  | ||||||
|    respected by the web server and the document is therefore sent in whole |  | ||||||
|    again, even though it doesn't match the requested condition. After reading |  | ||||||
|    section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do |  | ||||||
|    my own check as well. If curl thinks the condition isn't met, the transfer |  | ||||||
|    is aborted prematurely (after all the headers have been received). |  | ||||||
|  |  | ||||||
|  - After comments from Robert Linden I also rewrote some parts of the man page |  | ||||||
|    to better describe how the -F works. |  | ||||||
|  |  | ||||||
|  - Michael Anti put up a new curl download mirror in |  | ||||||
|    China:  http://www.pshowing.com/curl/ |  | ||||||
|  |  | ||||||
|  - I added the list of download mirrors to the README file |  | ||||||
|  |  | ||||||
|  - I did add more explanations to the man page |  | ||||||
|  |  | ||||||
|  Daniel (8 November 1999): |  | ||||||
|  - I made the -b/--cookie option capable of reading netscape formatted cookie |  | ||||||
|    files as well as normal http-header files. It should be able to |  | ||||||
|    transparently figure out what kind of file it got as input. |  | ||||||
|  |  | ||||||
|  Daniel (29 October 1999): |  | ||||||
|  - Another one of Sebastiaan van Erk's ideas (that has been requested before |  | ||||||
|    but I seem to have forgotten who it was), is to add support for ranges in |  | ||||||
|    FTP downloads. As usual, one request is just a request, when they're two |  | ||||||
|    it is a demand. I've added simple support for X-Y style fetches. X has to |  | ||||||
|    be the lower number, though you may omit one of the numbers. Use the -r/ |  | ||||||
|    --range switch (previously HTTP-only). |  | ||||||
|  |  | ||||||
|  - Sebastiaan van Erk suggested that curl should be |  | ||||||
|    able to show the file size of a specified file. I think this is a splendid |  | ||||||
|    idea and the -I flag is now working for FTP. It displays the file size in |  | ||||||
|    this manner: |  | ||||||
|         Content-Length: XXXX |  | ||||||
|    As it resembles normal headers, and leaves us the opportunity to add more |  | ||||||
|    info in that display if we can come up with more in the future! It also |  | ||||||
|    makes sense since if you access ftp through a HTTP proxy, you'd get the |  | ||||||
|    file size the same way. |  | ||||||
|  |  | ||||||
|    I changed the order of the QUOTE command executions. They're now executed |  | ||||||
|    just after the login and before any other command. I made this to enable |  | ||||||
|    quote commands to run before the -I stuff is done too. |  | ||||||
|  |  | ||||||
|  - I found out that -D/--dump-header and -V/--version weren't documented in |  | ||||||
|    the man page. |  | ||||||
|  |  | ||||||
|  - Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add |  | ||||||
|    some text about this in the man page for the range option. The thread in |  | ||||||
|    the mailing list that started this was initiated by Michael Anti. |  | ||||||
|  |  | ||||||
|  - I get reports about nroff crashes on solaris 2.6+ when displaying the curl |  | ||||||
|    man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay |  | ||||||
|    reported and brought the suggestion. |  | ||||||
|  |  | ||||||
|  - In a dialogue with Johannes G. Kristinsson we came |  | ||||||
|    up with the idea to let -H/--header specified headers replace the |  | ||||||
|    internally generated headers, if you happened to select to add a header |  | ||||||
|    that curl normally uses by itself. The advantage with this is not entirely |  | ||||||
|    obvious, but in Johannes' case it means that he can use another Host: than |  | ||||||
|    the one curl would set. |  | ||||||
|  |  | ||||||
|  Daniel (27 October 1999): |  | ||||||
|  - Jongki Suwandi brought a nice patch for (yet another) crash when following |  | ||||||
|    a location:. This time you had to follow a https:// server's redirect to |  | ||||||
|    get the core. |  | ||||||
|  |  | ||||||
| Version 6.2 |  | ||||||
|  |  | ||||||
|  Daniel (21 October 1999): |  | ||||||
|  - I think I managed to remove the suspicious (nil) that has been seen just |  | ||||||
|    before the "Host:" in HTTP requests when -v was used. |  | ||||||
|  - I found out that if you followed a location: when using a proxy, without |  | ||||||
|    having specified http:// in the URL, the protocol part was added once again |  | ||||||
|    when moving to the next URL! (The protocol part has to be added to the |  | ||||||
|    URL when going through a proxy since it has no protocol-guessing system |  | ||||||
|    such as curl has.) |  | ||||||
|  - Benjamin Ritcey reported a core dump under solaris 2.6 |  | ||||||
|    with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c |  | ||||||
|    that occurred after the download was done and completed. |  | ||||||
|  - Benjamin found ftp downloads to show the first line of the download meter |  | ||||||
|    to get written twice, and I removed that problem. It was introduced with |  | ||||||
|    the multiple URL support. |  | ||||||
|  - Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't |  | ||||||
|    honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are |  | ||||||
|    case-insensitive..."  HTTP header parsing assumed a certain casing. Dan |  | ||||||
|    also provided me with a patch that corrected this, which I took the liberty |  | ||||||
|    of editing slightly. |  | ||||||
|  - Dan Zitter also provided a nice patch for config.guess to better recognize |  | ||||||
|    the Mac OS X |  | ||||||
|  - Dan also corrected a minor problem in the lib/Makefile that caused linking |  | ||||||
|    to fail on OS X. |  | ||||||
|  |  | ||||||
|  Daniel (19 October 1999): |  | ||||||
|  - Len Marinaccio came up with some problems with curl.  Since Windows has a |  | ||||||
|    crippled shell, it can't redirect stderr and that causes trouble. I added |  | ||||||
|    --stderr today which allows the user to redirect the stderr stream to a |  | ||||||
|    file or stdout. |  | ||||||
|  |  | ||||||
|  Daniel (18 October 1999): |  | ||||||
|  - The configure script now understands the '--without-ssl' flag, which now |  | ||||||
|    totally disable SSL/https support. Previously it wasn't possible to force |  | ||||||
|    the configure script to leave SSL alone. The previous functionality has |  | ||||||
|    been retained. Troy Engel helped test this new one. |  | ||||||
|  |  | ||||||
| Version 6.1 |  | ||||||
|  |  | ||||||
|  Daniel (17 October 1999): |  | ||||||
|  - I ifdef'ed or commented all the zlib stuff in the sources and configure |  | ||||||
|    script. It turned out we needed to mock more with zlib than I initially |  | ||||||
|    thought, to make it capable of downloading compressed HTTP documents and |  | ||||||
|    uncompress them on the fly. I didn't mean the zlib parts of curl to become |  | ||||||
|    more than minor so this means I halt the zlib expedition for now and wait |  | ||||||
|    until someone either writes the code or zlib gets updated and better |  | ||||||
|    adjusted for this kind of usage.  I won't get into details here, but a |  | ||||||
|    short a summary is suitable: |  | ||||||
|    - zlib can't automatically detect whether to use zlib or gzip |  | ||||||
|      decompression methods. |  | ||||||
|    - zlib is very neat for reading gzipped files from a file descriptor, |  | ||||||
|      although not as nice for reading buffer-based data such as we would |  | ||||||
|      want it. |  | ||||||
|    - there are still some problems with the win32 version when reading from |  | ||||||
|      a file descriptor if that is a socket |  | ||||||
|  |  | ||||||
|  Daniel (14 October 1999): |  | ||||||
|  - Moved the (external) include files for libcurl into a subdirectory named |  | ||||||
|    curl and adjusted all #include lines to use <curl/XXXX> to maintain a |  | ||||||
|    better name space and control of the headers. This has been requested. |  | ||||||
|  |  | ||||||
|  Daniel (12 October 1999): |  | ||||||
|  - I modified the 'maketgz' script to perform a 'make' too before a release |  | ||||||
|    archive is put together in an attempt to make the time stamps better and |  | ||||||
|    hopefully avoid the double configure-running that use to occur. |  | ||||||
|  |  | ||||||
|  Daniel (11 October 1999): |  | ||||||
|  - Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as |  | ||||||
|    some other missing zlib #ifdef and more text on the multiple URL docs in |  | ||||||
|    the man page. |  | ||||||
|  |  | ||||||
| Version 6.1beta |  | ||||||
|  |  | ||||||
|  Daniel (6 October 1999): |  | ||||||
|  - Douglas E. Wegscheid sent me a patch that made the exact same thing as I |  | ||||||
|    just made: the -d switch is now capable of reading post data from a named |  | ||||||
|    file or stdin.  Use it similarly to the -F. To read the post data from a |  | ||||||
|    given file: |  | ||||||
|  |  | ||||||
|         curl -d @path/to/filename www.postsite.com |  | ||||||
|  |  | ||||||
|    or let curl read it out from stdin: |  | ||||||
|  |  | ||||||
|         curl -d @- www.postit.com |  | ||||||
|  |  | ||||||
|  J<>rn Hartroth (3 October 1999): |  | ||||||
|  - Brought some more patches for multiple URL functionality. The MIME |  | ||||||
|    separation ideas are almost scrapped now, and a custom separator is being |  | ||||||
|    used instead. This is still compile-time "flagged". |  | ||||||
|  |  | ||||||
|  Daniel |  | ||||||
|  - Updated curl.1 with multiple URL info. |  | ||||||
|  |  | ||||||
|  Daniel (30 September 1999): |  | ||||||
|  - Felix von Leitner brought openssl-check fixes for configure.in to work |  | ||||||
|    out-of-the-box when the openssl files are installed in the system default |  | ||||||
|    dirs. |  | ||||||
|  |  | ||||||
|  Daniel (28 September 1999) |  | ||||||
|  - Added libz functionality. This should enable decompressing gzip, compress |  | ||||||
|    or deflate encoding HTTP documents. It also makes curl send an accept that |  | ||||||
|    it accepts that kind of encoding. Compressed contents usually shortens |  | ||||||
|    download time. I *need* someone to tell me a site that uses compressed HTTP |  | ||||||
|    documents so that I can test this out properly. |  | ||||||
|  |  | ||||||
|  - As a result of the adding of zlib awareness, I changed the version string |  | ||||||
|    a little. I plan to add openldap version reporting in there too. |  | ||||||
|  |  | ||||||
|  Daniel (17 September 1999) |  | ||||||
|  - Made the -F option allow stdin when specifying files. By using '-' instead |  | ||||||
|    of file name, the data will be read from stdin. |  | ||||||
|  |  | ||||||
| Version 6.0 |  | ||||||
|  |  | ||||||
|  Daniel (13 September 1999) |  | ||||||
|  - Added -X/--http-request <request> to enable any HTTP command to be sent. |  | ||||||
|    Do not that your server has to support the exact string you enter. This |  | ||||||
|    should possibly a string like DELETE or TRACE. |  | ||||||
|  |  | ||||||
|  - Applied Douglas' mingw32-fixes for the makefiles. |  | ||||||
|  |  | ||||||
|  Daniel (10 September 1999) |  | ||||||
|  - Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP |  | ||||||
|    servers return code properly after the --quote commands were issued. It |  | ||||||
|    took anything non 200 as an error, when all 2XX codes should be accepted as |  | ||||||
|    OK. |  | ||||||
|  |  | ||||||
|  - Sending cookies to the same site in multiple lines like curl used to do |  | ||||||
|    turned out to be bad and breaking the cookie specs. Curl now sends all |  | ||||||
|    cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I |  | ||||||
|    doubt that many servers do use that syntax (yet). |  | ||||||
|  |  | ||||||
|  Daniel (8 September 1999) |  | ||||||
|  - J<>rn helped me make sure it still compiles nicely with mingw32 under win32. |  | ||||||
|  |  | ||||||
|  Daniel (7 September 1999) |  | ||||||
|  - FTP upload through proxy is now turned into a HTTP PUT. Requested by |  | ||||||
|    Stefan Kanthak. |  | ||||||
|  |  | ||||||
|  - Added the ldap files to the .m32 makefile. |  | ||||||
|  |  | ||||||
|  Daniel (3 September 1999) |  | ||||||
|  - Made cookie matching work while using HTTP proxy. |  | ||||||
|  |  | ||||||
|  Bjorn Reese (31 August 1999) |  | ||||||
|  - Passed his ldap:// patch. Note that this requires the openldap shared |  | ||||||
|    library to be installed and that LD_LIBRARY_PATH points to the |  | ||||||
|    directory where the lib will be found when curl is run with a |  | ||||||
|    ldap:// URL. |  | ||||||
|  |  | ||||||
|  J<>rn Hartroth (31 August 1999) |  | ||||||
|  - Made the Mingw32 makefiles into single files. |  | ||||||
|  - Made file:// work for Win32. The same code is now used for unix as well for |  | ||||||
|    performance reasons. |  | ||||||
|  |  | ||||||
|  Douglas E. Wegscheid (30 August 1999) |  | ||||||
|  - Patched the Mingw32 makefiles for SSL builds. |  | ||||||
|  |  | ||||||
|  Matthew Clarke (30 August 1999) |  | ||||||
|  - Made a cool patch for configure.in to allow --with-ssl to specify the |  | ||||||
|    root dir of the openssl installation, as in |  | ||||||
|  |  | ||||||
|         ./configure --with-ssl=/usr/ssl_here |  | ||||||
|  |  | ||||||
|  - Corrected the 'reconf' script to work better with some shells. |  | ||||||
|  |  | ||||||
|  J<>rn Hartroth (26 August 1999) |  | ||||||
|  - Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32 |  | ||||||
|    compiles. |  | ||||||
|  |  | ||||||
| Version 5.11 |  | ||||||
|  |  | ||||||
|  Daniel (25 August 1999) |  | ||||||
|  - John Weismiller pointed out a bug in the header-line |  | ||||||
|    realloc() system in download.c. |  | ||||||
|  |  | ||||||
|  - I added lib/file.[ch] to offer a first, simple, file:// support. It |  | ||||||
|    probably won't do much good on win32 system at this point, but I see it |  | ||||||
|    as a start. |  | ||||||
|  |  | ||||||
|  - Made the release archives get a Makefile in the root dir, which can be |  | ||||||
|    used to start the compiling/building process easier. I haven't really |  | ||||||
|    changed any INSTALL text yet, I wanted to get some feed-back on this |  | ||||||
|    first. |  | ||||||
|  |  | ||||||
|  Daniel (17 August 1999) |  | ||||||
|  - Another Location: bug. Curl didn't do proper relative locations if the |  | ||||||
|    original URL had cgi-parameters that contained a slash. Nusu's page |  | ||||||
|    again. |  | ||||||
|  |  | ||||||
|  - Corrected the NO_PROXY usage. It is a list of substrings that if one of |  | ||||||
|    them matches the tail of the host name it should connect to, curl should |  | ||||||
|    not use a proxy to connect there. Pointed out to me by Douglas |  | ||||||
|    E. Wegscheid.  I also changed the README text a little regarding this. |  | ||||||
|  |  | ||||||
|  Daniel (16 August 1999) |  | ||||||
|  - Fixed a memory bug with http-servers that sent Location: to a Location: |  | ||||||
|    page. Nusu's page showed this too. |  | ||||||
|  |  | ||||||
|  - Made cookies work a lot better. Setting the same cookie name several times |  | ||||||
|    used to add more cookies instead of replacing the former one which it |  | ||||||
|    should've. Nusu <nus at intergorj.ro> brought me an URL that made this |  | ||||||
|    painfully visible... |  | ||||||
|  |  | ||||||
|  Troy (15 August 1999) |  | ||||||
|  - Brought new .spec files as well as a patch for configure.in that lets the |  | ||||||
|    configure script find the openssl files better, even when the include |  | ||||||
|    files are in /usr/include/openssl |  | ||||||
|  |  | ||||||
| Version 5.10 |  | ||||||
|  |  | ||||||
|  Daniel (13 August 1999) |  | ||||||
|  - SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of |  | ||||||
|    OpenSSL. Now why couldn't they simply add a *new* function instead of |  | ||||||
|    modifying the parameters of an already existing function? This way, we get |  | ||||||
|    a compiler warning if compiling with 0.9.4 but not with earlier. So, I had |  | ||||||
|    to come up with a #if construction that deals with this... |  | ||||||
|  |  | ||||||
|  - Made curl output the SSL version number get displayed properly with 0.9.4. |  | ||||||
|  |  | ||||||
|  Troy (12 August 1999) |  | ||||||
|  - Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also |  | ||||||
|    a bit rearranged. |  | ||||||
|   |  | ||||||
|  Daniel (12 August 1999) |  | ||||||
|  - I had to copy a good <arpa/telnet.h> include file into the curl source |  | ||||||
|    tree to enable the silly win32 systems to compile. The distribution rights |  | ||||||
|    allows us to do that as long as the file remains unmodified. |  | ||||||
|  |  | ||||||
|  - I corrected a few minor things that made the compiler complain when |  | ||||||
|    -Wall -pedantic was used. |  | ||||||
|  |  | ||||||
|  - I'm moving the official curl web page to http://curl.haxx.nu. I think it |  | ||||||
|    will make it easier to remember as it is a lot shorter and less cryptic. |  | ||||||
|    The old one still works and shows the same info. |  | ||||||
|  |  | ||||||
|  Daniel (11 August 1999) |  | ||||||
|  - Albert Chin-A-Young mailed me another correction for NROFF in the |  | ||||||
|    configure.in that is supposed to be better for IRIX users. |  | ||||||
|  |  | ||||||
|  Daniel (10 August 1999) |  | ||||||
|  - Albert Chin-A-Young helped me with some stupid Makefile things, as well as |  | ||||||
|    some fiddling with the getdate.c stuff that he had problems with under |  | ||||||
|    HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate |  | ||||||
|    yacc or bison is found by the configure script. Since this is slightly new, |  | ||||||
|    we need to test the output getdate.c with win32 systems to make sure it |  | ||||||
|    still compiles there. |  | ||||||
|  |  | ||||||
|  Daniel (5 August 1999) |  | ||||||
|  - I've just setup a new mailing list with the intention to keep discussions |  | ||||||
|    around libcurl development in it. I mainly expect it to be for thoughts and |  | ||||||
|    brainstorming around a "next generation" library, rather than nitpicking |  | ||||||
|    about the current implementation or details in the current libcurl. |  | ||||||
|  |  | ||||||
|    To join our happy bunch of future-looking geeks, enter 'subscribe |  | ||||||
|    <address>' in the body of a mail and send it to |  | ||||||
|    libcurl-request@listserv.fts.frontec.se.  Curl bug reports, the usual curl |  | ||||||
|    talk and everything else should still be kept in this mailing list. I've |  | ||||||
|    started to archive this mailing list and have put the libcurl web page at |  | ||||||
|    www.fts.frontec.se/~dast/libcurl/. |  | ||||||
|  |  | ||||||
|  - Stefan Kanthak contacted me regarding a few problems in the configure |  | ||||||
|    script which he discovered when trying to make curl compile and build under |  | ||||||
|    Siemens SINIX-Z V5.42B2004! |  | ||||||
|  |  | ||||||
|  - Marcus Klein very accurately informed me that src/version.h was not present |  | ||||||
|    in the CVS repository. Oh, how silly... |  | ||||||
|  |  | ||||||
|  - Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet |  | ||||||
|    support. If you run curl like 'curl telnet://host' you'll get all output on |  | ||||||
|    the screen and curl will read input from stdin. You'll be able to login and |  | ||||||
|    run commands etc, but since the output is buffered, expect to get a little |  | ||||||
|    weird output. |  | ||||||
|  |  | ||||||
|    This is still in its infancy and it might get changed. We need your |  | ||||||
|    feed-back and input in how this is best done. |  | ||||||
|  |  | ||||||
|    WIN32 NOTE: I bet we'll get problems when trying to compile the current |  | ||||||
|    lib/telnet.c on win32, but I think we can sort them out in time. |  | ||||||
|  |  | ||||||
|  - David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be |  | ||||||
|    defined for getdate.c to compile properly on HP-UX 11.0. I updated the |  | ||||||
|    configure script to check for alloca.h which should make it. |  | ||||||
|  |  | ||||||
|  Daniel (4 August 1999) |  | ||||||
|  - I finally got to understand Marcus Klein's ftp download resume problem, |  | ||||||
|    which turns out to be due to different outputs from different ftp |  | ||||||
|    servers. It makes ftp download resuming a little trickier, but I've made |  | ||||||
|    some modifications I really believe will work for most ftp servers and I do |  | ||||||
|    hope you report if you have problems with this! |  | ||||||
|  |  | ||||||
|  - Added text about file transfer resuming to README.curl. |  | ||||||
|  |  | ||||||
|  Daniel (2 August 1999) |  | ||||||
|  - Applied a progress-bar patch from Lars J. Aas. It offers |  | ||||||
|    a new styled progress bar enabled with -#/--progress-bar.  |  | ||||||
|  |  | ||||||
|  T. Yamada <tai at imasy.or.jp> (30 July 1999) |  | ||||||
|  - It breaks with segfault when 1) curl is using .netrc to obtain |  | ||||||
|    username/password (option '-n'), and 2) is automatically redirected to |  | ||||||
|    another location (option '-L'). |  | ||||||
|  |  | ||||||
|    There is a small bug in lib/url.c (block starting from line 641), which |  | ||||||
|    tries to take out username/password from user- supplied command-line |  | ||||||
|    argument ('-u' option). This block is never executed on first attempt since |  | ||||||
|    CONF_USERPWD bit isn't set at first, but curl later turns it on when it |  | ||||||
|    checks for CONF_NETRC bit. So when curl tries to redo everything due to |  | ||||||
|    redirection, it segfaults trying to access *data->userpwd. |  | ||||||
|  |  | ||||||
| Version 5.9.1 |  | ||||||
|  |  | ||||||
|  Daniel (30 July 1999) |  | ||||||
|  - Steve Walch pointed out that there is a memory leak in the formdata |  | ||||||
|    functions. I added a FormFree() function that is now used and supposed to |  | ||||||
|    correct this flaw. |  | ||||||
|  |  | ||||||
|  - Mark Wotton reported: |  | ||||||
|    'curl -L https://www.cwa.com.au/' core dumps.  I managed to cure this by |  | ||||||
|    correcting the cleanup procedure. The bug seems to be gone with my OpenSSL |  | ||||||
|    0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I |  | ||||||
|    don't know whether it is curl or SSLeay that is to blame for that. |  | ||||||
|  |  | ||||||
|  - Marcus Klein: |  | ||||||
|    Reported an FTP upload resume bug that I really can't repeat nor understand. |  | ||||||
|    I leave it here so that it won't be forgotten. |  | ||||||
|  |  | ||||||
|  Daniel (29 July 1999) |  | ||||||
|  - Costya Shulyupin suggested support for longer URLs when following Location: |  | ||||||
|    and I could only agree and fix it! |  | ||||||
|  |  | ||||||
|  - Leigh Purdie found a problem in the upload/POST department. It turned out |  | ||||||
|    that http.c accidentaly cleared the pointer instead of the byte counter |  | ||||||
|    when supposed to. |  | ||||||
|  |  | ||||||
|  - Costya Shulyupin pointed out a problem with port numbers and Location:. If |  | ||||||
|    you had a server at a non-standard port that redirected to an URL using a |  | ||||||
|    standard port number, curl still used that first port number. |  | ||||||
|  |  | ||||||
|  - Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION |  | ||||||
|    and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on |  | ||||||
|    the 302-code that the follow location header outputs it will never show any |  | ||||||
|    html on location: pages. I have now made it look for >=400 codes if |  | ||||||
|    CONF_FOLLOWLOCATION is set. |  | ||||||
|  |  | ||||||
|  - 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph |  | ||||||
|    Beckmann). |  | ||||||
|  |  | ||||||
|  - Joshua Swink and Rick Welykochy were the first to point out to me that the |  | ||||||
|    latest OpenSSL package now have moved the standard include path. It is now |  | ||||||
|    in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl |  | ||||||
|    option for the configure script to use that as the primary path, and I |  | ||||||
|    leave the former path too to work with older packages of OpenSSL too. |  | ||||||
|  |  | ||||||
|  Daniel (9 June 1999) |  | ||||||
|  - I finally understood the IRIX problem and now it seem to compile on it! |  | ||||||
|    I am gonna remove those #define strcasecmp() things once and for all now. |  | ||||||
|  |  | ||||||
|  Daniel (4 June 1999) |  | ||||||
|  - I adjusted the FTP reply 227 parser to make the PASV command work better |  | ||||||
|    with more ftp servers. Appearantly the Roxen Challanger server replied |  | ||||||
|    something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro |  | ||||||
|    and Mark Butler brought a solution for it. |  | ||||||
|  |  | ||||||
|  Daniel (26 May 1999) |  | ||||||
|  - Rearranged. README is new, the old one is now README.curl and I added a |  | ||||||
|    README.libcurl with text I got from Ralph Beckmann. |  | ||||||
|  |  | ||||||
|  - I also updated the INSTALL text. |  | ||||||
|  |  | ||||||
|  Daniel (25 May 1999) |  | ||||||
|  - David Jonathan Lowsky correctly pointed out that curl didn't properly deal |  | ||||||
|    with form posting where the variable shouldn't have any content, as in curl |  | ||||||
|    -F "form=" www.site.com. It was now fixed. |  | ||||||
|  |  | ||||||
| Version 5.9 |  | ||||||
|  |  | ||||||
|  Daniel (22 May 1999) |  | ||||||
|  - I've got a bug report from Aaron Scarisbrick in which he states he has some |  | ||||||
|    problems with -L under FreeBSD 3.0. I have previously got another bug |  | ||||||
|    report from Stefan Grether which points at an error with similar sympthoms |  | ||||||
|    when using win32. I made the allocation of the new url string a bit faster |  | ||||||
|    and different, don't know if it actually improves anything though... |  | ||||||
|  |  | ||||||
|  Daniel (20 May 1999) |  | ||||||
|  - Made the cookie parser deal with CRLF newlines too. |  | ||||||
|  |  | ||||||
|  Daniel (19 May 1999) |  | ||||||
|  - Download() didn't properly deal with failing return codes from the sread() |  | ||||||
|    function. Adam Coyne found the problem in the win32 version, and Troy Engel |  | ||||||
|    helped me out isolating it. |  | ||||||
|  |  | ||||||
|  Daniel (16 May 1999) |  | ||||||
|  - Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't |  | ||||||
|    work anymore! :-/ I fixed it now. |  | ||||||
|  |  | ||||||
|  - After a suggestion by Joshua Swink I added -S / --show-error to force curl |  | ||||||
|    to display the error message in case of an error, even if -s/--silent was |  | ||||||
|    used. |  | ||||||
|  |  | ||||||
|  Daniel (10 May 1999) |  | ||||||
|  - I moved the stuff concerning HTTP, DICT and TELNET it their own source |  | ||||||
|    files now. It is a beginning on my clean-up of the sources to make them |  | ||||||
|    layer all those protocols better to enable more to be added easier in the |  | ||||||
|    future! |  | ||||||
|  |  | ||||||
|  - Leon Breedt sent me some files I've not put into the main curl |  | ||||||
|    archive. They're for creating the Debian package thingie. He also sent me a |  | ||||||
|    debian package that I've made available for download at the web page |  | ||||||
|  |  | ||||||
|  Daniel (9 May 1999) |  | ||||||
|  - Made it compile on cygwin too. |  | ||||||
|  |  | ||||||
|  Troy Engel (7 May 1999) |  | ||||||
|  - Brought a series of patches to allow curl to compile smoothly on MSVC++ 6 |  | ||||||
|    again! |  | ||||||
|  |  | ||||||
|  Daniel (6 May 1999) |  | ||||||
|  - I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it |  | ||||||
|    will be easier to discover systems that don't have that function and thus |  | ||||||
|    can't use -z successfully. Made the strftime() get used if WIN32 is defined |  | ||||||
|    too. |  | ||||||
|  |  | ||||||
| Version 5.8 |  | ||||||
|  |  | ||||||
|  Daniel (5 May 1999) |  | ||||||
|  - I've had it with this autoconf/automake mess. It seems to work allright |  | ||||||
|    for most people who don't have automake installed, but for those who have |  | ||||||
|    there are problems all over. |  | ||||||
|  |  | ||||||
|    I've got like five different bug reports on this only the last |  | ||||||
|    week... Claudio Neves and Federico Bianchi and root <duggerj001 at |  | ||||||
|    hawaii.rr.com> are some of them reporting this. |  | ||||||
|  |  | ||||||
|    Currently, I have no really good fix since I want to use automake myself to |  | ||||||
|    generate the Makefile.in files. I've found out that the @SHELL@-problems |  | ||||||
|    can often be fixed by manually invoking 'automake' in the archive root |  | ||||||
|    before you run ./configure... I've hacked my maketgz script now to fiddle |  | ||||||
|    a bit with this and my tests seem to work better than before at least! |  | ||||||
|  |  | ||||||
|  Daniel (4 May 1999) |  | ||||||
|  - mkhelp.pl has been doing badly lately. I corrected a case problem in |  | ||||||
|    the regexes. |  | ||||||
|  |  | ||||||
|  - I've now remade the -o option to not touch the file unless it needs to. |  | ||||||
|    I had to do this to make -z option really fine, since now you can make a |  | ||||||
|    curl fetch and use a local copy's time when downloading to that file, as |  | ||||||
|    in: |  | ||||||
|  |  | ||||||
|         curl -z dump -o dump remote.site.com/file.html |  | ||||||
|  |  | ||||||
|    This will only get the file if the remote one is newer than the local. |  | ||||||
|    I'm aware that this alters previous behaviour a little. Some scripts out |  | ||||||
|    there may depend on that the file is always touched... |  | ||||||
|  |  | ||||||
|  - Corrected a bug in the SSLv2/v3 selection. |  | ||||||
|  |  | ||||||
|  - Felix von Leitner requested that curl should be able to send |  | ||||||
|    "If-Modified-Since" headers, which indeed is a fair idea.  I implemented it |  | ||||||
|    right away! Try -z <expression> where expression is a full GNU date |  | ||||||
|    expression or a file name to get the date from! |  | ||||||
|  |  | ||||||
|  Stephan Lagerholm (30 Apr 1999) |  | ||||||
|  - Pointed out a problem with the src/Makefile for FreeBSD. The RM variable |  | ||||||
|    isn't set and causes the make to fail. |  | ||||||
|  |  | ||||||
|  Daniel (26 April 1999) |  | ||||||
|  - Am I silly or what? Irving Wolfe pointed out to me that the curl version |  | ||||||
|    number was not set properly. Hasn't been since 5.6. This was due to a bug |  | ||||||
|    in my maketgz script! |  | ||||||
|  |  | ||||||
|  David Eriksson (25 Apr 1999) |  | ||||||
|  - Found a bug in cookies.c that made it crash at times. |  | ||||||
|  |  | ||||||
| Version 5.7.1 |  | ||||||
|  |  | ||||||
|  Doug Kaufman (23 Apr 1999) |  | ||||||
|  - Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned |  | ||||||
|    below and the other one a correction in include/stdcheaders.h |  | ||||||
|  |  | ||||||
|  - Added a paragraph about compiling with the US-version of openssl to the |  | ||||||
|    INSTALL file. |  | ||||||
|  |  | ||||||
|  Daniel |  | ||||||
|  - New mailing list address. Info updated on the web page as well as in the |  | ||||||
|    README file |  | ||||||
|  |  | ||||||
|  Greg Onufer (20 Apr 1999) |  | ||||||
|  - hostip.c didn't compile properly on SunOS 5.5.1. |  | ||||||
|    It needs an #include <sys/types.h> |  | ||||||
|  |  | ||||||
| Version 5.7 |  | ||||||
|  |  | ||||||
|  Daniel (Apr 20 1999) |  | ||||||
|  - Decided to upload a non-beta version right now! |  | ||||||
|  |  | ||||||
|  - Made curl support any-length HTTP headers. The destination buffer is now |  | ||||||
|    simply enlarged every time it turns out to be too small! |  | ||||||
|  |  | ||||||
|  - Added the FAQ file to the archive. Still a bit smallish, but it is a |  | ||||||
|    start. |  | ||||||
|  |  | ||||||
|  Eric Thelin (15 Apr 1999) |  | ||||||
|  - Made -D accept '-' instead of filename to write to stdout. |  | ||||||
|  |  | ||||||
| Version 5.6.3beta |  | ||||||
|  |  | ||||||
|  Daniel (Apr 12 1999) |  | ||||||
|  |  | ||||||
|  - Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing |  | ||||||
|    in url.c and ftp.c. Makes cygwin32 deal with them better too. We should |  | ||||||
|    try to get some decent win32-replacement there. Anyone? |  | ||||||
|  |  | ||||||
|  - The old -3/--crlf option is now ONLY --crlf! |  | ||||||
|  |  | ||||||
|  - I changed the "SSL fix" to a more lame one, but that doesn't remove as |  | ||||||
|    much functionality. Now I've enabled the lib to select what SSL version it |  | ||||||
|    should try first. Appearantly some older SSL-servers don't like when you |  | ||||||
|    talk v3 with them so you need to be able to force curl to talk v2 from the |  | ||||||
|    start. The fix dated April 6 and posted on the mailing list forced curl to |  | ||||||
|    use v2 at all times using a modern OpenSSL version, but we don't really |  | ||||||
|    want such a crippled solution. |  | ||||||
|   |  | ||||||
|  - Marc Boucher sent me a patch that corrected a math error for the |  | ||||||
|    "Curr.Speed" progress meter. |  | ||||||
|  |  | ||||||
|  - Eric Thelin sent me a patch that enables '-K -' to read a config file from |  | ||||||
|    stdin. |  | ||||||
|  |  | ||||||
|  - I found out we didn't close the file properly before so I added it! |  | ||||||
|  |  | ||||||
|  Daniel (Apr 9 1999) |  | ||||||
|  - Yu Xin pointed out a problem with ftp download resume.  It didn't work at |  | ||||||
|    all! ;-O |  | ||||||
|  |  | ||||||
|  Daniel (Apr 6 1999) |  | ||||||
|  - Corrected the version string part generated for the SSL version. |  | ||||||
|  |  | ||||||
|  - I found a way to make some other SSL page work with openssl 0.9.1+ that |  | ||||||
|    previously didn't (ssleay 0.8.0 works with it though!). Trying to get |  | ||||||
|    some real info from the OpenSSL guys to see how I should do to behave the |  | ||||||
|    best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days! |  | ||||||
|  |  | ||||||
| Version 5.6.2beta |  | ||||||
|  |  | ||||||
|  Daniel (Apr 4 1999) |  | ||||||
|  - Finally have curl more cookie "aware". Now read carefully. This is how |  | ||||||
|    it works. |  | ||||||
|    To make curl read cookies from an already existing file, in plain header- |  | ||||||
|    format (like from the headers of a previous fetch) invoke curl with the |  | ||||||
|    -b flag like: |  | ||||||
|  |  | ||||||
|         curl -b file http://site/foo.html |  | ||||||
|  |  | ||||||
|    Curl will then use all cookies it finds matching. The old style that sets |  | ||||||
|    a single cookie with -b is still supported and is used if the string |  | ||||||
|    following -b includes a '=' letter, as in "-b name=daniel". |  | ||||||
|  |  | ||||||
|    To make curl read the cookies sent in combination with a location: (which |  | ||||||
|    sites often do) point curl to read a non-existing file at first (i.e |  | ||||||
|    to start with no existing cookies), like: |  | ||||||
|  |  | ||||||
|         curl -b nowhere http://site/setcookieandrelocate.html |  | ||||||
|  |  | ||||||
|  - Added a paragraph in the TODO file about the SSL problems recently |  | ||||||
|    reported. Evidently, some kind of SSL-problem curl may need to address. |  | ||||||
|  |  | ||||||
|  - Better "Location:" following. |  | ||||||
|  |  | ||||||
|  Douglas E. Wegscheid (Tue, 30 Mar 1999) |  | ||||||
|  - A subsecond display patch. |  | ||||||
|  |  | ||||||
|  Daniel (Mar 14 1999) |  | ||||||
|  - I've separated the version number of libcurl and curl now. To make |  | ||||||
|    things a little easier, I decided to start the curl numbering from |  | ||||||
|    5.6 and the former version number known as "curl" is now the one |  | ||||||
|    set for libcurl. |  | ||||||
|  |  | ||||||
|  - Removed the 'enable-no-pass' from configure, I doubt anyone wanted |  | ||||||
|    that. |  | ||||||
|  |  | ||||||
|  - Made lots of tiny adjustments to compile smoothly with cygwin under |  | ||||||
|    win32. It's a killer for porting this to win32, bye bye VC++! ;-) |  | ||||||
|    Compiles and builds out-of-the-box now. See the new wordings in |  | ||||||
|    INSTALL for details. |  | ||||||
|  |  | ||||||
|  - Beginning experiments with downloading multiple document from a http |  | ||||||
|    server while remaining connected. |  | ||||||
|  |  | ||||||
| Version 5.6beta |  | ||||||
|  |  | ||||||
|  Daniel (Mar 13 1999) |  | ||||||
|  - Since I've changed so much, I thought I'd just go ahead and implement the |  | ||||||
|    suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing |  | ||||||
|    HTTP headers separately in the specified file. |  | ||||||
|  |  | ||||||
|  - Added new text to INSTALL on what to do to build this on win32 now. |  | ||||||
|  |  | ||||||
|  - Aaargh. I had to take a step back and prefix the shared #include files |  | ||||||
|    in the sources with "../include/" to please VC++... |  | ||||||
|  |  | ||||||
|  Daniel (Mar 12 1999) |  | ||||||
|  - Split the url.c source into many tiny sources for better readability |  | ||||||
|    and smaller size. |  | ||||||
|  |  | ||||||
|  Daniel (Mar 11 1999) |  | ||||||
|  - Started to change stuff for a move to make libcurl and a more separate |  | ||||||
|    curl application that uses the libcurl. Made the libcurl sources into |  | ||||||
|    the new lib directory while the curl application will remain in src as |  | ||||||
|    before. New makefiles, adjusted configure script and so. |  | ||||||
|  |  | ||||||
|    libcurl.a built quickly and easily. I better make a better interface to |  | ||||||
|    the lib functions though. |  | ||||||
|  |  | ||||||
|    The new root dir include/ is supposed to contain the public information |  | ||||||
|    about the new libcurl. It is a little ugly so far :-) |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  Daniel (Mar 1 1999) |  | ||||||
|  - Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the |  | ||||||
|    info that RFC 2109 specifies how to use them.  The link is now in the |  | ||||||
|    README and the RFC in the RESOURCES. |  | ||||||
|  |  | ||||||
|  Daniel (Feb 23 1999) |  | ||||||
|  - Finally made configure accept --with-ssl to look for SSL libs and includes |  | ||||||
|    in the "standard" place /usr/local/ssl... |  | ||||||
|  |  | ||||||
|  Daniel (Feb 22 1999) |  | ||||||
|  - Verified that curl linked fine with OpenSSL 0.9.1c which seems to be |  | ||||||
|    the most recent. |  | ||||||
|  |  | ||||||
|  Henri Gomez (Fri Feb  5 1999) |  | ||||||
|  - Sent in an updated curl-ssl.spec. I still miss the script that builds an |  | ||||||
|    RPM automatically... |  | ||||||
|  |  | ||||||
| Version 5.5.1 |  | ||||||
|  |  | ||||||
|  Mark Butler (27 Jan 1999) |  | ||||||
|  - Corrected problems in Download(). |  | ||||||
|  |  | ||||||
|  Danitel Stenberg (25 Jan 1999) |  | ||||||
|  - Jeremie Petit pointed out a few flaws in the source that prevented it from |  | ||||||
|    compile warning free with the native compiler under Digital Unix v4.0d. |  | ||||||
|  |  | ||||||
| Version 5.5 |  | ||||||
|  |  | ||||||
|  Daniel Stenberg (15 Jan 1999) |  | ||||||
|  - Added Bjorns small text to the README about the DICT protocol. |  | ||||||
|  |  | ||||||
|  Daniel Stenberg (11 Jan 1999) |  | ||||||
|  - <jswink at softcom.net> reported about the win32-versioin: "Doesn't use |  | ||||||
|    ALL_PROXY environment variable". Turned out to be because of the static- |  | ||||||
|    buffer nature of the win32 environment variable calls! |  | ||||||
|  |  | ||||||
|  Bjorn Reese (10 Jan 1999) |  | ||||||
|  - I have attached a simple addition for the DICT protocol (RFC 2229). |  | ||||||
|    It performs dictionary lookups. The output still needs to be better |  | ||||||
|    formatted. |  | ||||||
|  |  | ||||||
|    To test it try (the exact format, and more examples are described in |  | ||||||
|    the RFC) |  | ||||||
|  |  | ||||||
|         dict://dict.org/m:hello |  | ||||||
|         dict://dict.org/m:hello::soundex |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  Vicente Garcia (10 Jan 1999) |  | ||||||
|  - Corrected the progress meter for files larger than 20MB. |  | ||||||
|  |  | ||||||
|  Daniel Stenberg (7 Jan 1999) |  | ||||||
|  - Corrected the -t and -T help texts. They claimed to be FTP only. |  | ||||||
|  |  | ||||||
| Version 5.4 |  | ||||||
|  |  | ||||||
|  Daniel Stenberg |  | ||||||
|  (7 Jan 1999) |  | ||||||
|  - Irving Wolfe reported that curl -s didn't always supress the progress |  | ||||||
|    reporting. It was the form post that autoamtically always switched it on |  | ||||||
|    again. This is now corrected! |  | ||||||
|  |  | ||||||
|  (4 Jan 1999) |  | ||||||
|  - Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If |  | ||||||
|    you use -t or -T now on a http or https server, PUT will be used for file |  | ||||||
|    upload. |  | ||||||
|  |  | ||||||
|    I removed the former use of -T with HTTP. I doubt anyone ever really used |  | ||||||
|    that. |  | ||||||
|  |  | ||||||
|  (4 Jan 1999) |  | ||||||
|  - Erik Jacobsen found a width bug in the mprintf() function.  I corrected it |  | ||||||
|    now. |  | ||||||
|  |  | ||||||
|  (4 Jan 1999) |  | ||||||
|  - As John V. Chow pointed out to me, curl accepted very limited URL sizes. It |  | ||||||
|    should now accept path parts that are up to at least 4096 bytes. |  | ||||||
|  |  | ||||||
|  - Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so |  | ||||||
|    I redid that now. |  | ||||||
|  |  | ||||||
| Version 5.3a (win32 only) | Version 5.3a (win32 only) | ||||||
|  |  | ||||||
|  Troy Engel |  Troy Engel | ||||||
|   | |||||||
							
								
								
									
										835
									
								
								CHANGES.1999
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										835
									
								
								CHANGES.1999
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,835 @@ | |||||||
|  | Daniel (28 December 1999): | ||||||
|  |  - Tim Verhoeven correctly identified that curl | ||||||
|  |    doesn't support URL formatted file names when getting ftp. Now, there's a | ||||||
|  |    problem with getting very weird file names off FTP servers. RFC 959 defines | ||||||
|  |    that the file name syntax to use should be the same as in the native OS of | ||||||
|  |    the server. Since we don't know the peer server system we currently just | ||||||
|  |    translate the URL syntax into plain letters. It is still better and with | ||||||
|  |    the solaris 2.6-supplied ftp server it works with spaces in the file names. | ||||||
|  |  | ||||||
|  | Daniel (27 December 1999): | ||||||
|  |  - When curl parsed cookies straight off a remote site, it corrupted the input | ||||||
|  |    data, which, if the downloaded headers were stored made very odd characters | ||||||
|  |    in the saved data. Correctly identified and reported by Paul Harrington. | ||||||
|  |  | ||||||
|  | Daniel (13 December 1999): | ||||||
|  |  - General cleanups in the library interface. There had been some bad kludges | ||||||
|  |    added during times of stress and I did my best to clean them off. It was | ||||||
|  |    both regarding the lib API as well as include file confusions. | ||||||
|  |  | ||||||
|  | Daniel (3 December 1999): | ||||||
|  |  - A small --stderr bug was reported by Eetu Ojanen... | ||||||
|  |  | ||||||
|  |  - who also brought the suggestion of extending the -X flag to ftp list as | ||||||
|  |    well. So, now it is and the long option is now --request instead. It is | ||||||
|  |    only for ftp list for now (and the former http stuff too of course). | ||||||
|  |  | ||||||
|  | Lars J. Aas (24 November 1999): | ||||||
|  |  - Patched curl to compile and build under BeOS. Doesn't work yet though! | ||||||
|  |  | ||||||
|  |  - Corrected the Makefile.am files to allow putting object files in | ||||||
|  |    different directories than the sources. | ||||||
|  |  | ||||||
|  | Version 6.3.1 | ||||||
|  |  | ||||||
|  | Daniel (23 November 1999): | ||||||
|  |  - I've had this major disk crash. My good old trust-worthy source disk died | ||||||
|  |    along with the machine that hosted it. Thank goodness most of all the | ||||||
|  |    things I've done are either backed up elsewhere or stored in this CVS | ||||||
|  |    server! | ||||||
|  |  | ||||||
|  |  - Michael S. Steuer pointed out a bug in the -F handling | ||||||
|  |    that made curl hang if you posted an empty variable such as '-F name='. It | ||||||
|  |    was one of those old bugs that never have worked properly... | ||||||
|  |  | ||||||
|  |  - Jason Baietto pointed out a general flaw in the HTTP | ||||||
|  |    download. Curl didn't complain if it was prematurely aborted before the | ||||||
|  |    entire download was completed. It does now. | ||||||
|  |  | ||||||
|  | Daniel (19 November 1999): | ||||||
|  |  - Chris Maltby very accurately criticized the lack of | ||||||
|  |    return code checks on the fwrite() calls. I did a thorough check for all | ||||||
|  |    occurrences and corrected this. | ||||||
|  |  | ||||||
|  | Daniel (17 November 1999): | ||||||
|  |  - Paul Harrington pointed out that the -m/--max-time option | ||||||
|  |    doesn't work for the slow system calls like gethostbyname()... I don't have | ||||||
|  |    any good fix yet, just a slightly less bad one that makes curl exit hard | ||||||
|  |    when the timeout is reached. | ||||||
|  |  | ||||||
|  |  - Bjorn Reese helped me point out a possible problem that might be the reason | ||||||
|  |    why Thomas Hurst experience problems in his Amiga version. | ||||||
|  |  | ||||||
|  |  Daniel (12 November 1999): | ||||||
|  |  - I found a crash in the new cookie file parser. It crashed when you gave | ||||||
|  |    a plain http header file as input... | ||||||
|  |  | ||||||
|  | Version 6.3 | ||||||
|  |  | ||||||
|  |  Daniel (10 November 1999): | ||||||
|  |  - I kind of found out that the HTTP time-conditional GETs (-z) aren't always | ||||||
|  |    respected by the web server and the document is therefore sent in whole | ||||||
|  |    again, even though it doesn't match the requested condition. After reading | ||||||
|  |    section 13.3.4 of RFC 2616, I think I'm doing the right thing now when I do | ||||||
|  |    my own check as well. If curl thinks the condition isn't met, the transfer | ||||||
|  |    is aborted prematurely (after all the headers have been received). | ||||||
|  |  | ||||||
|  |  - After comments from Robert Linden I also rewrote some parts of the man page | ||||||
|  |    to better describe how the -F works. | ||||||
|  |  | ||||||
|  |  - Michael Anti put up a new curl download mirror in | ||||||
|  |    China:  http://www.pshowing.com/curl/ | ||||||
|  |  | ||||||
|  |  - I added the list of download mirrors to the README file | ||||||
|  |  | ||||||
|  |  - I did add more explanations to the man page | ||||||
|  |  | ||||||
|  |  Daniel (8 November 1999): | ||||||
|  |  - I made the -b/--cookie option capable of reading netscape formatted cookie | ||||||
|  |    files as well as normal http-header files. It should be able to | ||||||
|  |    transparently figure out what kind of file it got as input. | ||||||
|  |  | ||||||
|  |  Daniel (29 October 1999): | ||||||
|  |  - Another one of Sebastiaan van Erk's ideas (that has been requested before | ||||||
|  |    but I seem to have forgotten who it was), is to add support for ranges in | ||||||
|  |    FTP downloads. As usual, one request is just a request, when they're two | ||||||
|  |    it is a demand. I've added simple support for X-Y style fetches. X has to | ||||||
|  |    be the lower number, though you may omit one of the numbers. Use the -r/ | ||||||
|  |    --range switch (previously HTTP-only). | ||||||
|  |  | ||||||
|  |  - Sebastiaan van Erk suggested that curl should be | ||||||
|  |    able to show the file size of a specified file. I think this is a splendid | ||||||
|  |    idea and the -I flag is now working for FTP. It displays the file size in | ||||||
|  |    this manner: | ||||||
|  |         Content-Length: XXXX | ||||||
|  |    As it resembles normal headers, and leaves us the opportunity to add more | ||||||
|  |    info in that display if we can come up with more in the future! It also | ||||||
|  |    makes sense since if you access ftp through a HTTP proxy, you'd get the | ||||||
|  |    file size the same way. | ||||||
|  |  | ||||||
|  |    I changed the order of the QUOTE command executions. They're now executed | ||||||
|  |    just after the login and before any other command. I made this to enable | ||||||
|  |    quote commands to run before the -I stuff is done too. | ||||||
|  |  | ||||||
|  |  - I found out that -D/--dump-header and -V/--version weren't documented in | ||||||
|  |    the man page. | ||||||
|  |  | ||||||
|  |  - Many HTTP/1.1 servers do not support ranges. Don't ask me why. I did add | ||||||
|  |    some text about this in the man page for the range option. The thread in | ||||||
|  |    the mailing list that started this was initiated by Michael Anti. | ||||||
|  |  | ||||||
|  |  - I get reports about nroff crashes on solaris 2.6+ when displaying the curl | ||||||
|  |    man page. Switch to gnroff instead, it is reported to work(!). Adam Barclay | ||||||
|  |    reported and brought the suggestion. | ||||||
|  |  | ||||||
|  |  - In a dialogue with Johannes G. Kristinsson we came | ||||||
|  |    up with the idea to let -H/--header specified headers replace the | ||||||
|  |    internally generated headers, if you happened to select to add a header | ||||||
|  |    that curl normally uses by itself. The advantage with this is not entirely | ||||||
|  |    obvious, but in Johannes' case it means that he can use another Host: than | ||||||
|  |    the one curl would set. | ||||||
|  |  | ||||||
|  |  Daniel (27 October 1999): | ||||||
|  |  - Jongki Suwandi brought a nice patch for (yet another) crash when following | ||||||
|  |    a location:. This time you had to follow a https:// server's redirect to | ||||||
|  |    get the core. | ||||||
|  |  | ||||||
|  | Version 6.2 | ||||||
|  |  | ||||||
|  |  Daniel (21 October 1999): | ||||||
|  |  - I think I managed to remove the suspicious (nil) that has been seen just | ||||||
|  |    before the "Host:" in HTTP requests when -v was used. | ||||||
|  |  - I found out that if you followed a location: when using a proxy, without | ||||||
|  |    having specified http:// in the URL, the protocol part was added once again | ||||||
|  |    when moving to the next URL! (The protocol part has to be added to the | ||||||
|  |    URL when going through a proxy since it has no protocol-guessing system | ||||||
|  |    such as curl has.) | ||||||
|  |  - Benjamin Ritcey reported a core dump under solaris 2.6 | ||||||
|  |    with OpenSSL 0.9.4. It turned out this was due to a bad free() in main.c | ||||||
|  |    that occurred after the download was done and completed. | ||||||
|  |  - Benjamin found ftp downloads to show the first line of the download meter | ||||||
|  |    to get written twice, and I removed that problem. It was introduced with | ||||||
|  |    the multiple URL support. | ||||||
|  |  - Dan Zitter correctly pointed out that curl 6.1 and earlier versions didn't | ||||||
|  |    honor RFC 2616 chapter 4 section 2, "Message Headers": "...Field names are | ||||||
|  |    case-insensitive..."  HTTP header parsing assumed a certain casing. Dan | ||||||
|  |    also provided me with a patch that corrected this, which I took the liberty | ||||||
|  |    of editing slightly. | ||||||
|  |  - Dan Zitter also provided a nice patch for config.guess to better recognize | ||||||
|  |    the Mac OS X | ||||||
|  |  - Dan also corrected a minor problem in the lib/Makefile that caused linking | ||||||
|  |    to fail on OS X. | ||||||
|  |  | ||||||
|  |  Daniel (19 October 1999): | ||||||
|  |  - Len Marinaccio came up with some problems with curl.  Since Windows has a | ||||||
|  |    crippled shell, it can't redirect stderr and that causes trouble. I added | ||||||
|  |    --stderr today which allows the user to redirect the stderr stream to a | ||||||
|  |    file or stdout. | ||||||
|  |  | ||||||
|  |  Daniel (18 October 1999): | ||||||
|  |  - The configure script now understands the '--without-ssl' flag, which now | ||||||
|  |    totally disable SSL/https support. Previously it wasn't possible to force | ||||||
|  |    the configure script to leave SSL alone. The previous functionality has | ||||||
|  |    been retained. Troy Engel helped test this new one. | ||||||
|  |  | ||||||
|  | Version 6.1 | ||||||
|  |  | ||||||
|  |  Daniel (17 October 1999): | ||||||
|  |  - I ifdef'ed or commented all the zlib stuff in the sources and configure | ||||||
|  |    script. It turned out we needed to mock more with zlib than I initially | ||||||
|  |    thought, to make it capable of downloading compressed HTTP documents and | ||||||
|  |    uncompress them on the fly. I didn't mean the zlib parts of curl to become | ||||||
|  |    more than minor so this means I halt the zlib expedition for now and wait | ||||||
|  |    until someone either writes the code or zlib gets updated and better | ||||||
|  |    adjusted for this kind of usage.  I won't get into details here, but a | ||||||
|  |    short a summary is suitable: | ||||||
|  |    - zlib can't automatically detect whether to use zlib or gzip | ||||||
|  |      decompression methods. | ||||||
|  |    - zlib is very neat for reading gzipped files from a file descriptor, | ||||||
|  |      although not as nice for reading buffer-based data such as we would | ||||||
|  |      want it. | ||||||
|  |    - there are still some problems with the win32 version when reading from | ||||||
|  |      a file descriptor if that is a socket | ||||||
|  |  | ||||||
|  |  Daniel (14 October 1999): | ||||||
|  |  - Moved the (external) include files for libcurl into a subdirectory named | ||||||
|  |    curl and adjusted all #include lines to use <curl/XXXX> to maintain a | ||||||
|  |    better name space and control of the headers. This has been requested. | ||||||
|  |  | ||||||
|  |  Daniel (12 October 1999): | ||||||
|  |  - I modified the 'maketgz' script to perform a 'make' too before a release | ||||||
|  |    archive is put together in an attempt to make the time stamps better and | ||||||
|  |    hopefully avoid the double configure-running that use to occur. | ||||||
|  |  | ||||||
|  |  Daniel (11 October 1999): | ||||||
|  |  - Applied J<>rn's patches that fixes zlib for mingw32 compiles as well as | ||||||
|  |    some other missing zlib #ifdef and more text on the multiple URL docs in | ||||||
|  |    the man page. | ||||||
|  |  | ||||||
|  | Version 6.1beta | ||||||
|  |  | ||||||
|  |  Daniel (6 October 1999): | ||||||
|  |  - Douglas E. Wegscheid sent me a patch that made the exact same thing as I | ||||||
|  |    just made: the -d switch is now capable of reading post data from a named | ||||||
|  |    file or stdin.  Use it similarly to the -F. To read the post data from a | ||||||
|  |    given file: | ||||||
|  |  | ||||||
|  |         curl -d @path/to/filename www.postsite.com | ||||||
|  |  | ||||||
|  |    or let curl read it out from stdin: | ||||||
|  |  | ||||||
|  |         curl -d @- www.postit.com | ||||||
|  |  | ||||||
|  |  J<>rn Hartroth (3 October 1999): | ||||||
|  |  - Brought some more patches for multiple URL functionality. The MIME | ||||||
|  |    separation ideas are almost scrapped now, and a custom separator is being | ||||||
|  |    used instead. This is still compile-time "flagged". | ||||||
|  |  | ||||||
|  |  Daniel | ||||||
|  |  - Updated curl.1 with multiple URL info. | ||||||
|  |  | ||||||
|  |  Daniel (30 September 1999): | ||||||
|  |  - Felix von Leitner brought openssl-check fixes for configure.in to work | ||||||
|  |    out-of-the-box when the openssl files are installed in the system default | ||||||
|  |    dirs. | ||||||
|  |  | ||||||
|  |  Daniel (28 September 1999) | ||||||
|  |  - Added libz functionality. This should enable decompressing gzip, compress | ||||||
|  |    or deflate encoding HTTP documents. It also makes curl send an accept that | ||||||
|  |    it accepts that kind of encoding. Compressed contents usually shortens | ||||||
|  |    download time. I *need* someone to tell me a site that uses compressed HTTP | ||||||
|  |    documents so that I can test this out properly. | ||||||
|  |  | ||||||
|  |  - As a result of the adding of zlib awareness, I changed the version string | ||||||
|  |    a little. I plan to add openldap version reporting in there too. | ||||||
|  |  | ||||||
|  |  Daniel (17 September 1999) | ||||||
|  |  - Made the -F option allow stdin when specifying files. By using '-' instead | ||||||
|  |    of file name, the data will be read from stdin. | ||||||
|  |  | ||||||
|  | Version 6.0 | ||||||
|  |  | ||||||
|  |  Daniel (13 September 1999) | ||||||
|  |  - Added -X/--http-request <request> to enable any HTTP command to be sent. | ||||||
|  |    Do not that your server has to support the exact string you enter. This | ||||||
|  |    should possibly a string like DELETE or TRACE. | ||||||
|  |  | ||||||
|  |  - Applied Douglas' mingw32-fixes for the makefiles. | ||||||
|  |  | ||||||
|  |  Daniel (10 September 1999) | ||||||
|  |  - Douglas E. Wegscheid pointed out a problem. Curl didn't check the FTP | ||||||
|  |    servers return code properly after the --quote commands were issued. It | ||||||
|  |    took anything non 200 as an error, when all 2XX codes should be accepted as | ||||||
|  |    OK. | ||||||
|  |  | ||||||
|  |  - Sending cookies to the same site in multiple lines like curl used to do | ||||||
|  |    turned out to be bad and breaking the cookie specs. Curl now sends all | ||||||
|  |    cookies on a single Cookie: line. Curl is not yet RFC 2109 compliant, but I | ||||||
|  |    doubt that many servers do use that syntax (yet). | ||||||
|  |  | ||||||
|  |  Daniel (8 September 1999) | ||||||
|  |  - J<>rn helped me make sure it still compiles nicely with mingw32 under win32. | ||||||
|  |  | ||||||
|  |  Daniel (7 September 1999) | ||||||
|  |  - FTP upload through proxy is now turned into a HTTP PUT. Requested by | ||||||
|  |    Stefan Kanthak. | ||||||
|  |  | ||||||
|  |  - Added the ldap files to the .m32 makefile. | ||||||
|  |  | ||||||
|  |  Daniel (3 September 1999) | ||||||
|  |  - Made cookie matching work while using HTTP proxy. | ||||||
|  |  | ||||||
|  |  Bjorn Reese (31 August 1999) | ||||||
|  |  - Passed his ldap:// patch. Note that this requires the openldap shared | ||||||
|  |    library to be installed and that LD_LIBRARY_PATH points to the | ||||||
|  |    directory where the lib will be found when curl is run with a | ||||||
|  |    ldap:// URL. | ||||||
|  |  | ||||||
|  |  J<>rn Hartroth (31 August 1999) | ||||||
|  |  - Made the Mingw32 makefiles into single files. | ||||||
|  |  - Made file:// work for Win32. The same code is now used for unix as well for | ||||||
|  |    performance reasons. | ||||||
|  |  | ||||||
|  |  Douglas E. Wegscheid (30 August 1999) | ||||||
|  |  - Patched the Mingw32 makefiles for SSL builds. | ||||||
|  |  | ||||||
|  |  Matthew Clarke (30 August 1999) | ||||||
|  |  - Made a cool patch for configure.in to allow --with-ssl to specify the | ||||||
|  |    root dir of the openssl installation, as in | ||||||
|  |  | ||||||
|  |         ./configure --with-ssl=/usr/ssl_here | ||||||
|  |  | ||||||
|  |  - Corrected the 'reconf' script to work better with some shells. | ||||||
|  |  | ||||||
|  |  J<>rn Hartroth (26 August 1999) | ||||||
|  |  - Fixed the Mingw32 makefiles in lib/ and corrected the file.c for win32 | ||||||
|  |    compiles. | ||||||
|  |  | ||||||
|  | Version 5.11 | ||||||
|  |  | ||||||
|  |  Daniel (25 August 1999) | ||||||
|  |  - John Weismiller pointed out a bug in the header-line | ||||||
|  |    realloc() system in download.c. | ||||||
|  |  | ||||||
|  |  - I added lib/file.[ch] to offer a first, simple, file:// support. It | ||||||
|  |    probably won't do much good on win32 system at this point, but I see it | ||||||
|  |    as a start. | ||||||
|  |  | ||||||
|  |  - Made the release archives get a Makefile in the root dir, which can be | ||||||
|  |    used to start the compiling/building process easier. I haven't really | ||||||
|  |    changed any INSTALL text yet, I wanted to get some feed-back on this | ||||||
|  |    first. | ||||||
|  |  | ||||||
|  |  Daniel (17 August 1999) | ||||||
|  |  - Another Location: bug. Curl didn't do proper relative locations if the | ||||||
|  |    original URL had cgi-parameters that contained a slash. Nusu's page | ||||||
|  |    again. | ||||||
|  |  | ||||||
|  |  - Corrected the NO_PROXY usage. It is a list of substrings that if one of | ||||||
|  |    them matches the tail of the host name it should connect to, curl should | ||||||
|  |    not use a proxy to connect there. Pointed out to me by Douglas | ||||||
|  |    E. Wegscheid.  I also changed the README text a little regarding this. | ||||||
|  |  | ||||||
|  |  Daniel (16 August 1999) | ||||||
|  |  - Fixed a memory bug with http-servers that sent Location: to a Location: | ||||||
|  |    page. Nusu's page showed this too. | ||||||
|  |  | ||||||
|  |  - Made cookies work a lot better. Setting the same cookie name several times | ||||||
|  |    used to add more cookies instead of replacing the former one which it | ||||||
|  |    should've. Nusu <nus at intergorj.ro> brought me an URL that made this | ||||||
|  |    painfully visible... | ||||||
|  |  | ||||||
|  |  Troy (15 August 1999) | ||||||
|  |  - Brought new .spec files as well as a patch for configure.in that lets the | ||||||
|  |    configure script find the openssl files better, even when the include | ||||||
|  |    files are in /usr/include/openssl | ||||||
|  |  | ||||||
|  | Version 5.10 | ||||||
|  |  | ||||||
|  |  Daniel (13 August 1999) | ||||||
|  |  - SSL_CTX_set_default_passwd_cb() has been modified in the 0.9.4 version of | ||||||
|  |    OpenSSL. Now why couldn't they simply add a *new* function instead of | ||||||
|  |    modifying the parameters of an already existing function? This way, we get | ||||||
|  |    a compiler warning if compiling with 0.9.4 but not with earlier. So, I had | ||||||
|  |    to come up with a #if construction that deals with this... | ||||||
|  |  | ||||||
|  |  - Made curl output the SSL version number get displayed properly with 0.9.4. | ||||||
|  |  | ||||||
|  |  Troy (12 August 1999) | ||||||
|  |  - Added MingW32 (GCC-2.95) support under Win32. The INSTALL file was also | ||||||
|  |    a bit rearranged. | ||||||
|  |   | ||||||
|  |  Daniel (12 August 1999) | ||||||
|  |  - I had to copy a good <arpa/telnet.h> include file into the curl source | ||||||
|  |    tree to enable the silly win32 systems to compile. The distribution rights | ||||||
|  |    allows us to do that as long as the file remains unmodified. | ||||||
|  |  | ||||||
|  |  - I corrected a few minor things that made the compiler complain when | ||||||
|  |    -Wall -pedantic was used. | ||||||
|  |  | ||||||
|  |  - I'm moving the official curl web page to http://curl.haxx.nu. I think it | ||||||
|  |    will make it easier to remember as it is a lot shorter and less cryptic. | ||||||
|  |    The old one still works and shows the same info. | ||||||
|  |  | ||||||
|  |  Daniel (11 August 1999) | ||||||
|  |  - Albert Chin-A-Young mailed me another correction for NROFF in the | ||||||
|  |    configure.in that is supposed to be better for IRIX users. | ||||||
|  |  | ||||||
|  |  Daniel (10 August 1999) | ||||||
|  |  - Albert Chin-A-Young helped me with some stupid Makefile things, as well as | ||||||
|  |    some fiddling with the getdate.c stuff that he had problems with under | ||||||
|  |    HP-UX v10. getdate.y will now be compiled into getdate.c if the appropriate | ||||||
|  |    yacc or bison is found by the configure script. Since this is slightly new, | ||||||
|  |    we need to test the output getdate.c with win32 systems to make sure it | ||||||
|  |    still compiles there. | ||||||
|  |  | ||||||
|  |  Daniel (5 August 1999) | ||||||
|  |  - I've just setup a new mailing list with the intention to keep discussions | ||||||
|  |    around libcurl development in it. I mainly expect it to be for thoughts and | ||||||
|  |    brainstorming around a "next generation" library, rather than nitpicking | ||||||
|  |    about the current implementation or details in the current libcurl. | ||||||
|  |  | ||||||
|  |    To join our happy bunch of future-looking geeks, enter 'subscribe | ||||||
|  |    <address>' in the body of a mail and send it to | ||||||
|  |    libcurl-request@listserv.fts.frontec.se.  Curl bug reports, the usual curl | ||||||
|  |    talk and everything else should still be kept in this mailing list. I've | ||||||
|  |    started to archive this mailing list and have put the libcurl web page at | ||||||
|  |    www.fts.frontec.se/~dast/libcurl/. | ||||||
|  |  | ||||||
|  |  - Stefan Kanthak contacted me regarding a few problems in the configure | ||||||
|  |    script which he discovered when trying to make curl compile and build under | ||||||
|  |    Siemens SINIX-Z V5.42B2004! | ||||||
|  |  | ||||||
|  |  - Marcus Klein very accurately informed me that src/version.h was not present | ||||||
|  |    in the CVS repository. Oh, how silly... | ||||||
|  |  | ||||||
|  |  - Linus Nielsen rewrote the telnet:// part and now curl offers limited telnet | ||||||
|  |    support. If you run curl like 'curl telnet://host' you'll get all output on | ||||||
|  |    the screen and curl will read input from stdin. You'll be able to login and | ||||||
|  |    run commands etc, but since the output is buffered, expect to get a little | ||||||
|  |    weird output. | ||||||
|  |  | ||||||
|  |    This is still in its infancy and it might get changed. We need your | ||||||
|  |    feed-back and input in how this is best done. | ||||||
|  |  | ||||||
|  |    WIN32 NOTE: I bet we'll get problems when trying to compile the current | ||||||
|  |    lib/telnet.c on win32, but I think we can sort them out in time. | ||||||
|  |  | ||||||
|  |  - David Sanderson reported that FORCE_ALLOCA_H or HAVE_ALLOCA_H must be | ||||||
|  |    defined for getdate.c to compile properly on HP-UX 11.0. I updated the | ||||||
|  |    configure script to check for alloca.h which should make it. | ||||||
|  |  | ||||||
|  |  Daniel (4 August 1999) | ||||||
|  |  - I finally got to understand Marcus Klein's ftp download resume problem, | ||||||
|  |    which turns out to be due to different outputs from different ftp | ||||||
|  |    servers. It makes ftp download resuming a little trickier, but I've made | ||||||
|  |    some modifications I really believe will work for most ftp servers and I do | ||||||
|  |    hope you report if you have problems with this! | ||||||
|  |  | ||||||
|  |  - Added text about file transfer resuming to README.curl. | ||||||
|  |  | ||||||
|  |  Daniel (2 August 1999) | ||||||
|  |  - Applied a progress-bar patch from Lars J. Aas. It offers | ||||||
|  |    a new styled progress bar enabled with -#/--progress-bar.  | ||||||
|  |  | ||||||
|  |  T. Yamada <tai at imasy.or.jp> (30 July 1999) | ||||||
|  |  - It breaks with segfault when 1) curl is using .netrc to obtain | ||||||
|  |    username/password (option '-n'), and 2) is automatically redirected to | ||||||
|  |    another location (option '-L'). | ||||||
|  |  | ||||||
|  |    There is a small bug in lib/url.c (block starting from line 641), which | ||||||
|  |    tries to take out username/password from user- supplied command-line | ||||||
|  |    argument ('-u' option). This block is never executed on first attempt since | ||||||
|  |    CONF_USERPWD bit isn't set at first, but curl later turns it on when it | ||||||
|  |    checks for CONF_NETRC bit. So when curl tries to redo everything due to | ||||||
|  |    redirection, it segfaults trying to access *data->userpwd. | ||||||
|  |  | ||||||
|  | Version 5.9.1 | ||||||
|  |  | ||||||
|  |  Daniel (30 July 1999) | ||||||
|  |  - Steve Walch pointed out that there is a memory leak in the formdata | ||||||
|  |    functions. I added a FormFree() function that is now used and supposed to | ||||||
|  |    correct this flaw. | ||||||
|  |  | ||||||
|  |  - Mark Wotton reported: | ||||||
|  |    'curl -L https://www.cwa.com.au/' core dumps.  I managed to cure this by | ||||||
|  |    correcting the cleanup procedure. The bug seems to be gone with my OpenSSL | ||||||
|  |    0.9.2b, although still occurs when I run the ~100 years old SSLeay 0.8.0. I | ||||||
|  |    don't know whether it is curl or SSLeay that is to blame for that. | ||||||
|  |  | ||||||
|  |  - Marcus Klein: | ||||||
|  |    Reported an FTP upload resume bug that I really can't repeat nor understand. | ||||||
|  |    I leave it here so that it won't be forgotten. | ||||||
|  |  | ||||||
|  |  Daniel (29 July 1999) | ||||||
|  |  - Costya Shulyupin suggested support for longer URLs when following Location: | ||||||
|  |    and I could only agree and fix it! | ||||||
|  |  | ||||||
|  |  - Leigh Purdie found a problem in the upload/POST department. It turned out | ||||||
|  |    that http.c accidentaly cleared the pointer instead of the byte counter | ||||||
|  |    when supposed to. | ||||||
|  |  | ||||||
|  |  - Costya Shulyupin pointed out a problem with port numbers and Location:. If | ||||||
|  |    you had a server at a non-standard port that redirected to an URL using a | ||||||
|  |    standard port number, curl still used that first port number. | ||||||
|  |  | ||||||
|  |  - Ralph Beckmann pointed out a problem when using both CONF_FOLLOWLOCATION | ||||||
|  |    and CONF_FAILONERROR simultaneously. Since the CONF_FAILONERROR exits on | ||||||
|  |    the 302-code that the follow location header outputs it will never show any | ||||||
|  |    html on location: pages. I have now made it look for >=400 codes if | ||||||
|  |    CONF_FOLLOWLOCATION is set. | ||||||
|  |  | ||||||
|  |  - 'struct slist' is now renamed to 'struct curl_slist' (as suggested by Ralph | ||||||
|  |    Beckmann). | ||||||
|  |  | ||||||
|  |  - Joshua Swink and Rick Welykochy were the first to point out to me that the | ||||||
|  |    latest OpenSSL package now have moved the standard include path. It is now | ||||||
|  |    in /usr/local/ssl/include/openssl and I have now modified the --enable-ssl | ||||||
|  |    option for the configure script to use that as the primary path, and I | ||||||
|  |    leave the former path too to work with older packages of OpenSSL too. | ||||||
|  |  | ||||||
|  |  Daniel (9 June 1999) | ||||||
|  |  - I finally understood the IRIX problem and now it seem to compile on it! | ||||||
|  |    I am gonna remove those #define strcasecmp() things once and for all now. | ||||||
|  |  | ||||||
|  |  Daniel (4 June 1999) | ||||||
|  |  - I adjusted the FTP reply 227 parser to make the PASV command work better | ||||||
|  |    with more ftp servers. Appearantly the Roxen Challanger server replied | ||||||
|  |    something curl 5.9 could deal with! :-( Reported by Ashley Reid-Montanaro | ||||||
|  |    and Mark Butler brought a solution for it. | ||||||
|  |  | ||||||
|  |  Daniel (26 May 1999) | ||||||
|  |  - Rearranged. README is new, the old one is now README.curl and I added a | ||||||
|  |    README.libcurl with text I got from Ralph Beckmann. | ||||||
|  |  | ||||||
|  |  - I also updated the INSTALL text. | ||||||
|  |  | ||||||
|  |  Daniel (25 May 1999) | ||||||
|  |  - David Jonathan Lowsky correctly pointed out that curl didn't properly deal | ||||||
|  |    with form posting where the variable shouldn't have any content, as in curl | ||||||
|  |    -F "form=" www.site.com. It was now fixed. | ||||||
|  |  | ||||||
|  | Version 5.9 | ||||||
|  |  | ||||||
|  |  Daniel (22 May 1999) | ||||||
|  |  - I've got a bug report from Aaron Scarisbrick in which he states he has some | ||||||
|  |    problems with -L under FreeBSD 3.0. I have previously got another bug | ||||||
|  |    report from Stefan Grether which points at an error with similar sympthoms | ||||||
|  |    when using win32. I made the allocation of the new url string a bit faster | ||||||
|  |    and different, don't know if it actually improves anything though... | ||||||
|  |  | ||||||
|  |  Daniel (20 May 1999) | ||||||
|  |  - Made the cookie parser deal with CRLF newlines too. | ||||||
|  |  | ||||||
|  |  Daniel (19 May 1999) | ||||||
|  |  - Download() didn't properly deal with failing return codes from the sread() | ||||||
|  |    function. Adam Coyne found the problem in the win32 version, and Troy Engel | ||||||
|  |    helped me out isolating it. | ||||||
|  |  | ||||||
|  |  Daniel (16 May 1999) | ||||||
|  |  - Richard Adams pointed out a bug I introduced in 5.8. --dump-header doesn't | ||||||
|  |    work anymore! :-/ I fixed it now. | ||||||
|  |  | ||||||
|  |  - After a suggestion by Joshua Swink I added -S / --show-error to force curl | ||||||
|  |    to display the error message in case of an error, even if -s/--silent was | ||||||
|  |    used. | ||||||
|  |  | ||||||
|  |  Daniel (10 May 1999) | ||||||
|  |  - I moved the stuff concerning HTTP, DICT and TELNET it their own source | ||||||
|  |    files now. It is a beginning on my clean-up of the sources to make them | ||||||
|  |    layer all those protocols better to enable more to be added easier in the | ||||||
|  |    future! | ||||||
|  |  | ||||||
|  |  - Leon Breedt sent me some files I've not put into the main curl | ||||||
|  |    archive. They're for creating the Debian package thingie. He also sent me a | ||||||
|  |    debian package that I've made available for download at the web page | ||||||
|  |  | ||||||
|  |  Daniel (9 May 1999) | ||||||
|  |  - Made it compile on cygwin too. | ||||||
|  |  | ||||||
|  |  Troy Engel (7 May 1999) | ||||||
|  |  - Brought a series of patches to allow curl to compile smoothly on MSVC++ 6 | ||||||
|  |    again! | ||||||
|  |  | ||||||
|  |  Daniel (6 May 1999) | ||||||
|  |  - I changed the #ifdef HAVE_STRFTIME placement for the -z code so that it | ||||||
|  |    will be easier to discover systems that don't have that function and thus | ||||||
|  |    can't use -z successfully. Made the strftime() get used if WIN32 is defined | ||||||
|  |    too. | ||||||
|  |  | ||||||
|  | Version 5.8 | ||||||
|  |  | ||||||
|  |  Daniel (5 May 1999) | ||||||
|  |  - I've had it with this autoconf/automake mess. It seems to work allright | ||||||
|  |    for most people who don't have automake installed, but for those who have | ||||||
|  |    there are problems all over. | ||||||
|  |  | ||||||
|  |    I've got like five different bug reports on this only the last | ||||||
|  |    week... Claudio Neves and Federico Bianchi and root <duggerj001 at | ||||||
|  |    hawaii.rr.com> are some of them reporting this. | ||||||
|  |  | ||||||
|  |    Currently, I have no really good fix since I want to use automake myself to | ||||||
|  |    generate the Makefile.in files. I've found out that the @SHELL@-problems | ||||||
|  |    can often be fixed by manually invoking 'automake' in the archive root | ||||||
|  |    before you run ./configure... I've hacked my maketgz script now to fiddle | ||||||
|  |    a bit with this and my tests seem to work better than before at least! | ||||||
|  |  | ||||||
|  |  Daniel (4 May 1999) | ||||||
|  |  - mkhelp.pl has been doing badly lately. I corrected a case problem in | ||||||
|  |    the regexes. | ||||||
|  |  | ||||||
|  |  - I've now remade the -o option to not touch the file unless it needs to. | ||||||
|  |    I had to do this to make -z option really fine, since now you can make a | ||||||
|  |    curl fetch and use a local copy's time when downloading to that file, as | ||||||
|  |    in: | ||||||
|  |  | ||||||
|  |         curl -z dump -o dump remote.site.com/file.html | ||||||
|  |  | ||||||
|  |    This will only get the file if the remote one is newer than the local. | ||||||
|  |    I'm aware that this alters previous behaviour a little. Some scripts out | ||||||
|  |    there may depend on that the file is always touched... | ||||||
|  |  | ||||||
|  |  - Corrected a bug in the SSLv2/v3 selection. | ||||||
|  |  | ||||||
|  |  - Felix von Leitner requested that curl should be able to send | ||||||
|  |    "If-Modified-Since" headers, which indeed is a fair idea.  I implemented it | ||||||
|  |    right away! Try -z <expression> where expression is a full GNU date | ||||||
|  |    expression or a file name to get the date from! | ||||||
|  |  | ||||||
|  |  Stephan Lagerholm (30 Apr 1999) | ||||||
|  |  - Pointed out a problem with the src/Makefile for FreeBSD. The RM variable | ||||||
|  |    isn't set and causes the make to fail. | ||||||
|  |  | ||||||
|  |  Daniel (26 April 1999) | ||||||
|  |  - Am I silly or what? Irving Wolfe pointed out to me that the curl version | ||||||
|  |    number was not set properly. Hasn't been since 5.6. This was due to a bug | ||||||
|  |    in my maketgz script! | ||||||
|  |  | ||||||
|  |  David Eriksson (25 Apr 1999) | ||||||
|  |  - Found a bug in cookies.c that made it crash at times. | ||||||
|  |  | ||||||
|  | Version 5.7.1 | ||||||
|  |  | ||||||
|  |  Doug Kaufman (23 Apr 1999) | ||||||
|  |  - Brought two sunos 4 fixes. One of them being the hostip.c fix mentioned | ||||||
|  |    below and the other one a correction in include/stdcheaders.h | ||||||
|  |  | ||||||
|  |  - Added a paragraph about compiling with the US-version of openssl to the | ||||||
|  |    INSTALL file. | ||||||
|  |  | ||||||
|  |  Daniel | ||||||
|  |  - New mailing list address. Info updated on the web page as well as in the | ||||||
|  |    README file | ||||||
|  |  | ||||||
|  |  Greg Onufer (20 Apr 1999) | ||||||
|  |  - hostip.c didn't compile properly on SunOS 5.5.1. | ||||||
|  |    It needs an #include <sys/types.h> | ||||||
|  |  | ||||||
|  | Version 5.7 | ||||||
|  |  | ||||||
|  |  Daniel (Apr 20 1999) | ||||||
|  |  - Decided to upload a non-beta version right now! | ||||||
|  |  | ||||||
|  |  - Made curl support any-length HTTP headers. The destination buffer is now | ||||||
|  |    simply enlarged every time it turns out to be too small! | ||||||
|  |  | ||||||
|  |  - Added the FAQ file to the archive. Still a bit smallish, but it is a | ||||||
|  |    start. | ||||||
|  |  | ||||||
|  |  Eric Thelin (15 Apr 1999) | ||||||
|  |  - Made -D accept '-' instead of filename to write to stdout. | ||||||
|  |  | ||||||
|  | Version 5.6.3beta | ||||||
|  |  | ||||||
|  |  Daniel (Apr 12 1999) | ||||||
|  |  | ||||||
|  |  - Changed two #ifdef WIN32 to better #ifdef <errorcode> when connect()ing | ||||||
|  |    in url.c and ftp.c. Makes cygwin32 deal with them better too. We should | ||||||
|  |    try to get some decent win32-replacement there. Anyone? | ||||||
|  |  | ||||||
|  |  - The old -3/--crlf option is now ONLY --crlf! | ||||||
|  |  | ||||||
|  |  - I changed the "SSL fix" to a more lame one, but that doesn't remove as | ||||||
|  |    much functionality. Now I've enabled the lib to select what SSL version it | ||||||
|  |    should try first. Appearantly some older SSL-servers don't like when you | ||||||
|  |    talk v3 with them so you need to be able to force curl to talk v2 from the | ||||||
|  |    start. The fix dated April 6 and posted on the mailing list forced curl to | ||||||
|  |    use v2 at all times using a modern OpenSSL version, but we don't really | ||||||
|  |    want such a crippled solution. | ||||||
|  |   | ||||||
|  |  - Marc Boucher sent me a patch that corrected a math error for the | ||||||
|  |    "Curr.Speed" progress meter. | ||||||
|  |  | ||||||
|  |  - Eric Thelin sent me a patch that enables '-K -' to read a config file from | ||||||
|  |    stdin. | ||||||
|  |  | ||||||
|  |  - I found out we didn't close the file properly before so I added it! | ||||||
|  |  | ||||||
|  |  Daniel (Apr 9 1999) | ||||||
|  |  - Yu Xin pointed out a problem with ftp download resume.  It didn't work at | ||||||
|  |    all! ;-O | ||||||
|  |  | ||||||
|  |  Daniel (Apr 6 1999) | ||||||
|  |  - Corrected the version string part generated for the SSL version. | ||||||
|  |  | ||||||
|  |  - I found a way to make some other SSL page work with openssl 0.9.1+ that | ||||||
|  |    previously didn't (ssleay 0.8.0 works with it though!). Trying to get | ||||||
|  |    some real info from the OpenSSL guys to see how I should do to behave the | ||||||
|  |    best way. SSLeay 0.8.0 shouldn't be that much in use anyway these days! | ||||||
|  |  | ||||||
|  | Version 5.6.2beta | ||||||
|  |  | ||||||
|  |  Daniel (Apr 4 1999) | ||||||
|  |  - Finally have curl more cookie "aware". Now read carefully. This is how | ||||||
|  |    it works. | ||||||
|  |    To make curl read cookies from an already existing file, in plain header- | ||||||
|  |    format (like from the headers of a previous fetch) invoke curl with the | ||||||
|  |    -b flag like: | ||||||
|  |  | ||||||
|  |         curl -b file http://site/foo.html | ||||||
|  |  | ||||||
|  |    Curl will then use all cookies it finds matching. The old style that sets | ||||||
|  |    a single cookie with -b is still supported and is used if the string | ||||||
|  |    following -b includes a '=' letter, as in "-b name=daniel". | ||||||
|  |  | ||||||
|  |    To make curl read the cookies sent in combination with a location: (which | ||||||
|  |    sites often do) point curl to read a non-existing file at first (i.e | ||||||
|  |    to start with no existing cookies), like: | ||||||
|  |  | ||||||
|  |         curl -b nowhere http://site/setcookieandrelocate.html | ||||||
|  |  | ||||||
|  |  - Added a paragraph in the TODO file about the SSL problems recently | ||||||
|  |    reported. Evidently, some kind of SSL-problem curl may need to address. | ||||||
|  |  | ||||||
|  |  - Better "Location:" following. | ||||||
|  |  | ||||||
|  |  Douglas E. Wegscheid (Tue, 30 Mar 1999) | ||||||
|  |  - A subsecond display patch. | ||||||
|  |  | ||||||
|  |  Daniel (Mar 14 1999) | ||||||
|  |  - I've separated the version number of libcurl and curl now. To make | ||||||
|  |    things a little easier, I decided to start the curl numbering from | ||||||
|  |    5.6 and the former version number known as "curl" is now the one | ||||||
|  |    set for libcurl. | ||||||
|  |  | ||||||
|  |  - Removed the 'enable-no-pass' from configure, I doubt anyone wanted | ||||||
|  |    that. | ||||||
|  |  | ||||||
|  |  - Made lots of tiny adjustments to compile smoothly with cygwin under | ||||||
|  |    win32. It's a killer for porting this to win32, bye bye VC++! ;-) | ||||||
|  |    Compiles and builds out-of-the-box now. See the new wordings in | ||||||
|  |    INSTALL for details. | ||||||
|  |  | ||||||
|  |  - Beginning experiments with downloading multiple document from a http | ||||||
|  |    server while remaining connected. | ||||||
|  |  | ||||||
|  | Version 5.6beta | ||||||
|  |  | ||||||
|  |  Daniel (Mar 13 1999) | ||||||
|  |  - Since I've changed so much, I thought I'd just go ahead and implement the | ||||||
|  |    suggestion from Douglas E. Wegscheid. -D or --dump-header is now storing | ||||||
|  |    HTTP headers separately in the specified file. | ||||||
|  |  | ||||||
|  |  - Added new text to INSTALL on what to do to build this on win32 now. | ||||||
|  |  | ||||||
|  |  - Aaargh. I had to take a step back and prefix the shared #include files | ||||||
|  |    in the sources with "../include/" to please VC++... | ||||||
|  |  | ||||||
|  |  Daniel (Mar 12 1999) | ||||||
|  |  - Split the url.c source into many tiny sources for better readability | ||||||
|  |    and smaller size. | ||||||
|  |  | ||||||
|  |  Daniel (Mar 11 1999) | ||||||
|  |  - Started to change stuff for a move to make libcurl and a more separate | ||||||
|  |    curl application that uses the libcurl. Made the libcurl sources into | ||||||
|  |    the new lib directory while the curl application will remain in src as | ||||||
|  |    before. New makefiles, adjusted configure script and so. | ||||||
|  |  | ||||||
|  |    libcurl.a built quickly and easily. I better make a better interface to | ||||||
|  |    the lib functions though. | ||||||
|  |  | ||||||
|  |    The new root dir include/ is supposed to contain the public information | ||||||
|  |    about the new libcurl. It is a little ugly so far :-) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  Daniel (Mar 1 1999) | ||||||
|  |  - Todd Kaufmann sent me a good link to Netscape's cookie spec as well as the | ||||||
|  |    info that RFC 2109 specifies how to use them.  The link is now in the | ||||||
|  |    README and the RFC in the RESOURCES. | ||||||
|  |  | ||||||
|  |  Daniel (Feb 23 1999) | ||||||
|  |  - Finally made configure accept --with-ssl to look for SSL libs and includes | ||||||
|  |    in the "standard" place /usr/local/ssl... | ||||||
|  |  | ||||||
|  |  Daniel (Feb 22 1999) | ||||||
|  |  - Verified that curl linked fine with OpenSSL 0.9.1c which seems to be | ||||||
|  |    the most recent. | ||||||
|  |  | ||||||
|  |  Henri Gomez (Fri Feb  5 1999) | ||||||
|  |  - Sent in an updated curl-ssl.spec. I still miss the script that builds an | ||||||
|  |    RPM automatically... | ||||||
|  |  | ||||||
|  | Version 5.5.1 | ||||||
|  |  | ||||||
|  |  Mark Butler (27 Jan 1999) | ||||||
|  |  - Corrected problems in Download(). | ||||||
|  |  | ||||||
|  |  Danitel Stenberg (25 Jan 1999) | ||||||
|  |  - Jeremie Petit pointed out a few flaws in the source that prevented it from | ||||||
|  |    compile warning free with the native compiler under Digital Unix v4.0d. | ||||||
|  |  | ||||||
|  | Version 5.5 | ||||||
|  |  | ||||||
|  |  Daniel Stenberg (15 Jan 1999) | ||||||
|  |  - Added Bjorns small text to the README about the DICT protocol. | ||||||
|  |  | ||||||
|  |  Daniel Stenberg (11 Jan 1999) | ||||||
|  |  - <jswink at softcom.net> reported about the win32-versioin: "Doesn't use | ||||||
|  |    ALL_PROXY environment variable". Turned out to be because of the static- | ||||||
|  |    buffer nature of the win32 environment variable calls! | ||||||
|  |  | ||||||
|  |  Bjorn Reese (10 Jan 1999) | ||||||
|  |  - I have attached a simple addition for the DICT protocol (RFC 2229). | ||||||
|  |    It performs dictionary lookups. The output still needs to be better | ||||||
|  |    formatted. | ||||||
|  |  | ||||||
|  |    To test it try (the exact format, and more examples are described in | ||||||
|  |    the RFC) | ||||||
|  |  | ||||||
|  |         dict://dict.org/m:hello | ||||||
|  |         dict://dict.org/m:hello::soundex | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  Vicente Garcia (10 Jan 1999) | ||||||
|  |  - Corrected the progress meter for files larger than 20MB. | ||||||
|  |  | ||||||
|  |  Daniel Stenberg (7 Jan 1999) | ||||||
|  |  - Corrected the -t and -T help texts. They claimed to be FTP only. | ||||||
|  |  | ||||||
|  | Version 5.4 | ||||||
|  |  | ||||||
|  |  Daniel Stenberg | ||||||
|  |  (7 Jan 1999) | ||||||
|  |  - Irving Wolfe reported that curl -s didn't always supress the progress | ||||||
|  |    reporting. It was the form post that autoamtically always switched it on | ||||||
|  |    again. This is now corrected! | ||||||
|  |  | ||||||
|  |  (4 Jan 1999) | ||||||
|  |  - Andreas Kostyrka suggested I'd add PUT and he helped me out to test it. If | ||||||
|  |    you use -t or -T now on a http or https server, PUT will be used for file | ||||||
|  |    upload. | ||||||
|  |  | ||||||
|  |    I removed the former use of -T with HTTP. I doubt anyone ever really used | ||||||
|  |    that. | ||||||
|  |  | ||||||
|  |  (4 Jan 1999) | ||||||
|  |  - Erik Jacobsen found a width bug in the mprintf() function.  I corrected it | ||||||
|  |    now. | ||||||
|  |  | ||||||
|  |  (4 Jan 1999) | ||||||
|  |  - As John V. Chow pointed out to me, curl accepted very limited URL sizes. It | ||||||
|  |    should now accept path parts that are up to at least 4096 bytes. | ||||||
|  |  | ||||||
|  |  - Somehow I screwed up when applying the AIX fix from Gilbert Ramirez, so | ||||||
|  |    I redid that now. | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								CVS-INFO
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								CVS-INFO
									
									
									
									
									
								
							| @@ -10,14 +10,10 @@ This file is only present in the CVS - never in release archives. It contains | |||||||
| information about other files and things that the CVS repository keeps in its | information about other files and things that the CVS repository keeps in its | ||||||
| inner sanctum. | inner sanctum. | ||||||
|  |  | ||||||
| Use autoconf 2.50 and no earlier. Also, try having automake 1.5 and libtool | Compile and build instructions follow below. | ||||||
| 1.4.1 at least. |  | ||||||
|  |  | ||||||
| You will need perl to generate the src/hugehelp.c file. The file |  | ||||||
| src/hugehelp.c.cvs is a one-shot file that you can rename to src/hugehelp.c if |  | ||||||
| you really can't generate the true file yourself! |  | ||||||
|  |  | ||||||
|   CHANGES.0     contains ancient changes. |   CHANGES.0     contains ancient changes. | ||||||
|  |   CHANGES.$year contains changes for the particular year. | ||||||
|  |  | ||||||
|   memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG |   memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG | ||||||
|                 is used when compiling |                 is used when compiling | ||||||
| @@ -26,12 +22,38 @@ you really can't generate the true file yourself! | |||||||
|  |  | ||||||
|   Makefile.dist is included as the root Makefile in distribution archives |   Makefile.dist is included as the root Makefile in distribution archives | ||||||
|  |  | ||||||
|   perl/contrib/ is a subdirectory with various perl scripts |   perl/         is a subdirectory with various perl scripts | ||||||
|  |  | ||||||
|   java/         is a subdirectory with the Java interface to libcurl |  | ||||||
|  |  | ||||||
| To build after having extracted everything from CVS, do this: | To build after having extracted everything from CVS, do this: | ||||||
|  |  | ||||||
| ./buildconf | ./buildconf | ||||||
| ./configure | ./configure | ||||||
| make | make | ||||||
|  |  | ||||||
|  | REQUIREMENTS | ||||||
|  |  | ||||||
|  |  You need the following software installed: | ||||||
|  |  | ||||||
|  |  o autoconf 2.50 (or later) | ||||||
|  |  o automake 1.5 (or later) | ||||||
|  |  o libtool  1.4 (or later) | ||||||
|  |  o GNU m4 (required by autoconf) | ||||||
|  |  | ||||||
|  |  o nroff + perl (if you don't have nroff and perl and you for some reason | ||||||
|  |    don't want to install them, you can rename the source file | ||||||
|  |    src/hugehelp.c.cvs to src/hugehelp.c and avoid having to generate this | ||||||
|  |    file. This will of course give you an older version of the file that isn't | ||||||
|  |    up-to-date. That file was checked in once and won't be updated very | ||||||
|  |    regularly.) | ||||||
|  |  | ||||||
|  | MAC OS X | ||||||
|  |  | ||||||
|  |  For Mac OS X users, Guido Neitzer write down the following step-by-step guide: | ||||||
|  |  | ||||||
|  |  1. Install fink (http://fink.sourceforge.net) | ||||||
|  |  2. Update fink to the newest version (with the installed fink) | ||||||
|  |  3. Install the latest version of autoconf, automake and m4 with fink | ||||||
|  |  4. Install version 1.4.1 of libtool - you find it in the "unstable" section | ||||||
|  |     (read the manual to see how to get unstable versions) | ||||||
|  |  5. Get cURL from the cvs | ||||||
|  |  6. Build cURL with "./buildconf", "./configure", "make", "sudo make install" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								LEGAL
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LEGAL
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
|  Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. |  Copyright (C) 1998-2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  | ||||||
|  Everyone is permitted to copy and distribute verbatim copies of this license |  Everyone is permitted to copy and distribute verbatim copies of this license | ||||||
|  document, but changing it is not allowed. |  document, but changing it is not allowed. | ||||||
|   | |||||||
| @@ -6,13 +6,11 @@ AUTOMAKE_OPTIONS = foreign no-dependencies | |||||||
|  |  | ||||||
| EXTRA_DIST =						\ | EXTRA_DIST =						\ | ||||||
| 	CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt	\ | 	CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt	\ | ||||||
| 	config-win32.h reconf Makefile.dist		\ | 	reconf Makefile.dist curl-config.in build_vms.com curl-mode.el | ||||||
| 	curl-config.in build_vms.com config-riscos.h	\ |  | ||||||
| 	config-vms.h curl-mode.el |  | ||||||
|  |  | ||||||
| bin_SCRIPTS = curl-config | bin_SCRIPTS = curl-config | ||||||
|  |  | ||||||
| SUBDIRS = docs lib src include tests packages | SUBDIRS = docs lib src include tests packages multi | ||||||
|  |  | ||||||
| # create a root makefile in the distribution: | # create a root makefile in the distribution: | ||||||
| dist-hook: | dist-hook: | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #                            | (__| |_| |  _ <| |___  | #                            | (__| |_| |  _ <| |___  | ||||||
| #                             \___|\___/|_| \_\_____| | #                             \___|\___/|_| \_\_____| | ||||||
| # | # | ||||||
| # Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. | # Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
| # | # | ||||||
| # In order to be useful for every potential user, curl and libcurl are | # In order to be useful for every potential user, curl and libcurl are | ||||||
| # dual-licensed under the MPL and the MIT/X-derivate licenses. | # dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
| @@ -43,13 +43,19 @@ mingw32-ssl: | |||||||
|  |  | ||||||
| vc: | vc: | ||||||
| 	cd lib | 	cd lib | ||||||
| 	nmake -f Makefile.vc6 | 	nmake -f Makefile.vc6 cfg=release | ||||||
| 	cd ..\src | 	cd ..\src | ||||||
| 	nmake -f Makefile.vc6 | 	nmake -f Makefile.vc6 | ||||||
|  |  | ||||||
| vc-ssl: | vc-ssl: | ||||||
| 	cd lib | 	cd lib | ||||||
| 	nmake -f Makefile.vc6 release-ssl | 	nmake -f Makefile.vc6 cfg=release-ssl | ||||||
|  | 	cd ..\src | ||||||
|  | 	nmake -f Makefile.vc6 cfg=release-ssl | ||||||
|  |  | ||||||
|  | vc-ssl-dll: | ||||||
|  | 	cd lib | ||||||
|  | 	nmake -f Makefile.vc6 cfg=release-ssl-dll | ||||||
| 	cd ..\src | 	cd ..\src | ||||||
| 	nmake -f Makefile.vc6 | 	nmake -f Makefile.vc6 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| @@ -26,7 +26,7 @@ README | |||||||
|   The official download mirror sites are: |   The official download mirror sites are: | ||||||
|  |  | ||||||
|         Sweden    -- ftp://ftp.sunet.se/pub/www/utilities/curl/ |         Sweden    -- ftp://ftp.sunet.se/pub/www/utilities/curl/ | ||||||
|         Sweden    -- ftp://cool.haxx.se/curl/ |         Sweden    -- http://cool.haxx.se/curl/ | ||||||
|         Germany   -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/ |         Germany   -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/ | ||||||
|  |  | ||||||
|   To download the very latest source off the CVS server do this: |   To download the very latest source off the CVS server do this: | ||||||
|   | |||||||
| @@ -62,3 +62,5 @@ | |||||||
| #undef HAVE_O_NONBLOCK | #undef HAVE_O_NONBLOCK | ||||||
| #undef HAVE_DISABLED_NONBLOCKING | #undef HAVE_DISABLED_NONBLOCKING | ||||||
|  |  | ||||||
|  | /* Define this to 'int' if in_addr_t is not an available typedefed type */ | ||||||
|  | #undef in_addr_t | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								acinclude.m4
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								acinclude.m4
									
									
									
									
									
								
							| @@ -143,6 +143,43 @@ AC_DEFUN([TYPE_SOCKLEN_T], | |||||||
| #include <sys/socket.h>]) | #include <sys/socket.h>]) | ||||||
| ]) | ]) | ||||||
|  |  | ||||||
|  | dnl Check for in_addr_t: it is used to receive the return code of inet_addr() | ||||||
|  | dnl and a few other things. If not found, we set it to unsigned int, as even | ||||||
|  | dnl 64-bit implementations use to set it to a 32-bit type. | ||||||
|  | AC_DEFUN([TYPE_IN_ADDR_T], | ||||||
|  | [ | ||||||
|  |    AC_CHECK_TYPE([in_addr_t], ,[ | ||||||
|  |       AC_MSG_CHECKING([for in_addr_t equivalent]) | ||||||
|  |       AC_CACHE_VAL([curl_cv_in_addr_t_equiv], | ||||||
|  |       [ | ||||||
|  |          # Systems have either "struct sockaddr *" or | ||||||
|  |          # "void *" as the second argument to getpeername | ||||||
|  |          curl_cv_in_addr_t_equiv= | ||||||
|  |          for t in int size_t unsigned long "unsigned long"; do | ||||||
|  |             AC_TRY_COMPILE([ | ||||||
|  |                #include <sys/types.h> | ||||||
|  |                #include <sys/socket.h> | ||||||
|  |                #include <arpa/inet.h> | ||||||
|  |             ],[ | ||||||
|  |                $t data = inet_addr ("1.2.3.4"); | ||||||
|  |             ],[ | ||||||
|  |                curl_cv_in_addr_t_equiv="$t" | ||||||
|  |                break | ||||||
|  |             ]) | ||||||
|  |          done | ||||||
|  |  | ||||||
|  |          if test "x$curl_cv_in_addr_t_equiv" = x; then | ||||||
|  |             AC_MSG_ERROR([Cannot find a type to use in place of in_addr_t]) | ||||||
|  |          fi | ||||||
|  |       ]) | ||||||
|  |       AC_MSG_RESULT($curl_cv_in_addr_t_equiv) | ||||||
|  |       AC_DEFINE_UNQUOTED(in_addr_t, $curl_cv_in_addr_t_equiv, | ||||||
|  | 			[type to use in place of in_addr_t if not defined])], | ||||||
|  |       [#include <sys/types.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <arpa/inet.h>]) | ||||||
|  | ]) | ||||||
|  |  | ||||||
| dnl ************************************************************ | dnl ************************************************************ | ||||||
| dnl check for "localhost", if it doesn't exist, we can't do the | dnl check for "localhost", if it doesn't exist, we can't do the | ||||||
| dnl gethostbyname_r tests! | dnl gethostbyname_r tests! | ||||||
| @@ -335,9 +372,12 @@ AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R, | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
|  | #undef NULL | ||||||
|  | #define NULL (void *)0 | ||||||
|  |  | ||||||
| int | int | ||||||
| gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[ | gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[ | ||||||
|  | struct hostent_data data; | ||||||
| gethostbyname_r(NULL, NULL, NULL);],[ | gethostbyname_r(NULL, NULL, NULL);],[ | ||||||
|       AC_MSG_RESULT(yes) |       AC_MSG_RESULT(yes) | ||||||
|       AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) |       AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) | ||||||
| @@ -350,9 +390,12 @@ gethostbyname_r(NULL, NULL, NULL);],[ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
|  | #undef NULL | ||||||
|  | #define NULL (void *)0 | ||||||
|  |  | ||||||
| int | int | ||||||
| gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[ | gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[ | ||||||
|  | struct hostent_data data; | ||||||
| gethostbyname_r(NULL, NULL, NULL);],[ | gethostbyname_r(NULL, NULL, NULL);],[ | ||||||
| 	AC_MSG_RESULT(yes) | 	AC_MSG_RESULT(yes) | ||||||
| 	AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) | 	AC_DEFINE(HAVE_GETHOSTBYNAME_R_3) | ||||||
| @@ -363,6 +406,8 @@ gethostbyname_r(NULL, NULL, NULL);],[ | |||||||
| 	AC_TRY_COMPILE([ | 	AC_TRY_COMPILE([ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
|  | #undef NULL | ||||||
|  | #define NULL (void *)0 | ||||||
|  |  | ||||||
| struct hostent * | struct hostent * | ||||||
| gethostbyname_r(const char *, struct hostent *, char *, int, int *);],[ | gethostbyname_r(const char *, struct hostent *, char *, int, int *);],[ | ||||||
| @@ -375,6 +420,8 @@ gethostbyname_r(NULL, NULL, NULL, 0, NULL);],[ | |||||||
| 	  AC_TRY_COMPILE([ | 	  AC_TRY_COMPILE([ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
|  | #undef NULL | ||||||
|  | #define NULL (void *)0 | ||||||
|  |  | ||||||
| int | int | ||||||
| gethostbyname_r(const char *, struct hostent *, char *, size_t, | gethostbyname_r(const char *, struct hostent *, char *, size_t, | ||||||
|   | |||||||
| @@ -6,14 +6,16 @@ $	loc  = f$environment("PROCEDURE") | |||||||
| $	def = f$parse("X.X;1",loc) - "X.X;1" | $	def = f$parse("X.X;1",loc) - "X.X;1" | ||||||
| $ | $ | ||||||
| $	set def 'def' | $	set def 'def' | ||||||
| $	cc_qual = "/define=HAVE_CONFIG_H=1/include=(""../include/"",""../"")" | $	cc_qual = "/define=HAVE_CONFIG_H=1/include=(""../include/"",""../"",""../../openssl-0_9_6c/include/"")" | ||||||
| $	if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE" | $	if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE" | ||||||
| $	if p1 .eqs. "DEBUG" then cc_qual = cc_qual + "/LIST/MACHINE/DEBUG" | $	if p1 .eqs. "DEBUG" then cc_qual = cc_qual + "/LIST/MACHINE/DEBUG" | ||||||
| $	msg_qual = "" | $	msg_qual = "" | ||||||
| $	call build "[.lib]" "*.c" | $	call build "[.lib]" "*.c" | ||||||
| $	call build "[.src]" "*.c" | $	call build "[.src]" "*.c" | ||||||
| $	call build "[.src]" "*.msg" | $	call build "[.src]" "*.msg" | ||||||
| $	link /exe=curl.exe [.src]curl/lib/include=main,[.lib]curl/lib | $	link /exe=curl.exe [.src]curl/lib/include=main,[.lib]curl/lib, - | ||||||
|  | 		[-.openssl-0_9_6c.axp.exe.ssl]libssl/lib, - | ||||||
|  | 		[-.openssl-0_9_6c.axp.exe.crypto]libcrypto/lib | ||||||
| $ | $ | ||||||
| $ | $ | ||||||
| $	goto Common_Exit | $	goto Common_Exit | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ die(){ | |||||||
| 	exit | 	exit | ||||||
| } | } | ||||||
|  |  | ||||||
| automake          || die "The command 'automake $MAKEFILES' failed" |  | ||||||
| aclocal           || die "The command 'aclocal' failed" | aclocal           || die "The command 'aclocal' failed" | ||||||
| autoheader        || die "The command 'autoheader' failed" | autoheader        || die "The command 'autoheader' failed" | ||||||
| autoconf          || die "The command 'autoconf' failed" | autoconf          || die "The command 'autoconf' failed" | ||||||
|  | automake          || die "The command 'automake $MAKEFILES' failed" | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								configure.in
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ AC_PREREQ(2.50) | |||||||
| dnl First some basic init macros | dnl First some basic init macros | ||||||
| AC_INIT | AC_INIT | ||||||
| AC_CONFIG_SRCDIR([lib/urldata.h]) | AC_CONFIG_SRCDIR([lib/urldata.h]) | ||||||
| AM_CONFIG_HEADER(config.h src/config.h) | AM_CONFIG_HEADER(lib/config.h src/config.h) | ||||||
|  |  | ||||||
| dnl figure out the libcurl version | dnl figure out the libcurl version | ||||||
| VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h` | VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h` | ||||||
| @@ -69,7 +69,7 @@ AC_ARG_ENABLE(debug, | |||||||
|   *)   AC_MSG_RESULT(yes) |   *)   AC_MSG_RESULT(yes) | ||||||
|  |  | ||||||
|     CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG" |     CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG" | ||||||
|     CFLAGS="-W -Wall -Wwrite-strings -pedantic -g"  |     CFLAGS="-W -Wall -Wwrite-strings -pedantic -Wundef -Wpointer-arith -Wcast-align -Wnested-externs -g"  | ||||||
|        ;; |        ;; | ||||||
|   esac ], |   esac ], | ||||||
|        AC_MSG_RESULT(no) |        AC_MSG_RESULT(no) | ||||||
| @@ -392,6 +392,10 @@ else | |||||||
|         OPENSSL_ENABLED=1) |         OPENSSL_ENABLED=1) | ||||||
|     fi |     fi | ||||||
|  |  | ||||||
|  |     dnl Check for the OpenSSL engine header, it is kind of "separated" | ||||||
|  |     dnl from the main SSL check | ||||||
|  |     AC_CHECK_HEADERS(openssl/engine.h) | ||||||
|  |  | ||||||
|     AC_SUBST(OPENSSL_ENABLED) |     AC_SUBST(OPENSSL_ENABLED) | ||||||
|  |  | ||||||
|   fi |   fi | ||||||
| @@ -469,6 +473,8 @@ else | |||||||
|   dnl is there a localtime_r() |   dnl is there a localtime_r() | ||||||
|   CURL_CHECK_LOCALTIME_R() |   CURL_CHECK_LOCALTIME_R() | ||||||
|  |  | ||||||
|  |   AC_CHECK_FUNCS( gmtime_r ) | ||||||
|  |  | ||||||
| fi | fi | ||||||
|  |  | ||||||
| dnl ********************************************************************** | dnl ********************************************************************** | ||||||
| @@ -492,7 +498,6 @@ AC_CHECK_HEADERS( \ | |||||||
|         sys/stat.h \ |         sys/stat.h \ | ||||||
|         sys/types.h \ |         sys/types.h \ | ||||||
|         sys/time.h \ |         sys/time.h \ | ||||||
|         getopt.h \ |  | ||||||
|         sys/param.h \ |         sys/param.h \ | ||||||
|         termios.h \ |         termios.h \ | ||||||
|         termio.h \ |         termio.h \ | ||||||
| @@ -519,14 +524,15 @@ AC_HEADER_TIME | |||||||
| # mprintf() checks: | # mprintf() checks: | ||||||
|  |  | ||||||
| # check for 'long double' | # check for 'long double' | ||||||
| AC_CHECK_SIZEOF(long double, 8) | # AC_CHECK_SIZEOF(long double, 8) | ||||||
| # check for 'long long' | # check for 'long long' | ||||||
| AC_CHECK_SIZEOF(long long, 4) | # AC_CHECK_SIZEOF(long long, 4) | ||||||
|  |  | ||||||
| # check for ssize_t | # check for ssize_t | ||||||
| AC_CHECK_TYPE(ssize_t, int) | AC_CHECK_TYPE(ssize_t, int) | ||||||
|  |  | ||||||
| TYPE_SOCKLEN_T | TYPE_SOCKLEN_T | ||||||
|  | TYPE_IN_ADDR_T | ||||||
|  |  | ||||||
| dnl Checks for library functions. | dnl Checks for library functions. | ||||||
| dnl AC_PROG_GCC_TRADITIONAL | dnl AC_PROG_GCC_TRADITIONAL | ||||||
| @@ -591,6 +597,7 @@ AC_CONFIG_FILES([Makefile \ | |||||||
| 	   include/Makefile \ | 	   include/Makefile \ | ||||||
| 	   include/curl/Makefile \ | 	   include/curl/Makefile \ | ||||||
| 	   src/Makefile \ | 	   src/Makefile \ | ||||||
|  | 	   multi/Makefile \ | ||||||
|            lib/Makefile \ |            lib/Makefile \ | ||||||
|            tests/Makefile \ |            tests/Makefile \ | ||||||
|            tests/data/Makefile \ |            tests/data/Makefile \ | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ Usage: curl-config [OPTION] | |||||||
|  |  | ||||||
| Available values for OPTION include: | Available values for OPTION include: | ||||||
|  |  | ||||||
|  |   --cc        compiler | ||||||
|   --cflags    pre-processor and compiler flags |   --cflags    pre-processor and compiler flags | ||||||
|   --feature   newline separated list of enabled features |   --feature   newline separated list of enabled features | ||||||
|   --help      display this help and exit |   --help      display this help and exit | ||||||
| @@ -42,6 +43,10 @@ while test $# -gt 0; do | |||||||
|     esac |     esac | ||||||
|  |  | ||||||
|     case "$1" in |     case "$1" in | ||||||
|  |     --cc) | ||||||
|  | 	echo @CC@ | ||||||
|  | 	;; | ||||||
|  |  | ||||||
|     --prefix) |     --prefix) | ||||||
| 	echo $prefix | 	echo $prefix | ||||||
| 	;; | 	;; | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								docs/BUGS
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								docs/BUGS
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | $Id$ | ||||||
|                                   _   _ ____  _      |                                   _   _ ____  _      | ||||||
|                               ___| | | |  _ \| |     |                               ___| | | |  _ \| |     | ||||||
|                              / __| | | | |_) | |     |                              / __| | | | |_) | |     | ||||||
| @@ -22,11 +23,16 @@ BUGS | |||||||
|  |  | ||||||
|   When reporting a bug, you should include information that will help us |   When reporting a bug, you should include information that will help us | ||||||
|   understand what's wrong, what you expected to happen and how to repeat the |   understand what's wrong, what you expected to happen and how to repeat the | ||||||
|   bad behaviour. You therefore need to supply your operating system's name and |   bad behavior. You therefore need to supply your operating system's name and | ||||||
|   version number (uname -a under a unix is fine), what version of curl you're |   version number (uname -a under a unix is fine), what version of curl you're | ||||||
|   using (curl -V is fine), what URL you were working with and anything else |   using (curl -V is fine), what URL you were working with and anything else | ||||||
|   you think matters. |   you think matters. | ||||||
|  |  | ||||||
|  |   Since curl deals with networks, it often helps us a lot if you include a | ||||||
|  |   protocol debug dump with your bug report. The output you get by using the -v | ||||||
|  |   flag. Usually, you also get more info by using -i so that is likely to be | ||||||
|  |   useful when reporting bugs as well. | ||||||
|  |  | ||||||
|   If curl crashed, causing a core dump (in unix), there is hardly any use to |   If curl crashed, causing a core dump (in unix), there is hardly any use to | ||||||
|   send that huge file to anyone of us. Unless we have an exact same system |   send that huge file to anyone of us. Unless we have an exact same system | ||||||
|   setup as you, we can't do much with it. What we instead ask of you is to get |   setup as you, we can't do much with it. What we instead ask of you is to get | ||||||
| @@ -35,23 +41,23 @@ BUGS | |||||||
|   The address and how to subscribe to the mailing list is detailed in the |   The address and how to subscribe to the mailing list is detailed in the | ||||||
|   MANUAL file. |   MANUAL file. | ||||||
|  |  | ||||||
|   HOW TO GET A STACK TRACE with a common unix debugger | HOW TO GET A STACK TRACE | ||||||
|   ==================================================== |  | ||||||
|  |  | ||||||
|   First, you must make sure that you compile all sources with -g and that you |   First, you must make sure that you compile all sources with -g and that you | ||||||
|   don't 'strip' the final executable. |   don't 'strip' the final executable. Try to avoid optimizing the code as | ||||||
|  |   well, remove -O, -O2 etc from the compiler options. | ||||||
|  |  | ||||||
|   Run the program until it bangs. |   Run the program until it dumps core. | ||||||
|  |  | ||||||
|   Run your debugger on the core file, like '<debugger> curl core'. <debugger> |   Run your debugger on the core file, like '<debugger> curl core'. <debugger> | ||||||
|   should be replaced with the name of your debugger, in most cases that will |   should be replaced with the name of your debugger, in most cases that will | ||||||
|   be 'gdb', but 'dbx' and others also occur. |   be 'gdb', but 'dbx' and others also occur. | ||||||
|  |  | ||||||
|   When the debugger has finished loading the core file and presents you a |   When the debugger has finished loading the core file and presents you a | ||||||
|   prompt, you can give the compiler instructions. Enter 'where' (without the |   prompt, enter 'where' (without the quotes) and press return. | ||||||
|   quotes) and press return. |  | ||||||
|  |  | ||||||
|   The list that is presented is the stack trace. If everything worked, it is |   The list that is presented is the stack trace. If everything worked, it is | ||||||
|   supposed to contain the chain of functions that were called when curl |   supposed to contain the chain of functions that were called when curl | ||||||
|   crashed. |   crashed. Include the stack trace with your detailed bug report. It'll help a | ||||||
|  |   lot. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								docs/FAQ
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								docs/FAQ
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| Updated: November 1, 2001 (http://curl.haxx.se/docs/faq.shtml) | Updated: January 22, 2002 (http://curl.haxx.se/docs/faq.shtml) | ||||||
|                                   _   _ ____  _      |                                   _   _ ____  _      | ||||||
|                               ___| | | |  _ \| |     |                               ___| | | |  _ \| |     | ||||||
|                              / __| | | | |_) | |     |                              / __| | | | |_) | |     | ||||||
| @@ -33,10 +33,10 @@ FAQ | |||||||
|   3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y? |   3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y? | ||||||
|   3.7 Can I use curl to delete/rename a file through FTP? |   3.7 Can I use curl to delete/rename a file through FTP? | ||||||
|   3.8 How do I tell curl to follow HTTP redirects? |   3.8 How do I tell curl to follow HTTP redirects? | ||||||
|   3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java? |   3.9 How do I use curl in my favourite programming language? | ||||||
|   3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? |   3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? | ||||||
|   3.11 How do I POST with a different Content-Type? |   3.11 How do I POST with a different Content-Type? | ||||||
|   3.12 Why do FTP specific features over HTTP proxy fails? |   3.12 Why do FTP specific features over HTTP proxy fail? | ||||||
|  |  | ||||||
|  4. Running Problems |  4. Running Problems | ||||||
|   4.1 Problems connecting to SSL servers. |   4.1 Problems connecting to SSL servers. | ||||||
| @@ -49,6 +49,7 @@ FAQ | |||||||
|    4.5.3 "403 Forbidden" |    4.5.3 "403 Forbidden" | ||||||
|    4.5.4 "404 Not Found" |    4.5.4 "404 Not Found" | ||||||
|    4.5.5 "405 Method Not Allowed" |    4.5.5 "405 Method Not Allowed" | ||||||
|  |    4.5.6 "301 Moved Permanently" | ||||||
|   4.6 Can you tell me what error code 142 means? |   4.6 Can you tell me what error code 142 means? | ||||||
|   4.7 How do I keep user names and passwords secret in Curl command lines? |   4.7 How do I keep user names and passwords secret in Curl command lines? | ||||||
|   4.8 I found a bug! |   4.8 I found a bug! | ||||||
| @@ -154,26 +155,27 @@ FAQ | |||||||
|   have them inserted in the main sources (of course on the condition that |   have them inserted in the main sources (of course on the condition that | ||||||
|   developers agree on that the fixes are good). |   developers agree on that the fixes are good). | ||||||
|  |  | ||||||
|   The list of contributors in the bottom of the man page is only a small part |   The list of contributors in the docs/THANKS file is only a small part of all | ||||||
|   of all the people that every day provide us with bug reports, suggestions, |   the people that every day provide us with bug reports, suggestions, ideas | ||||||
|   ideas and source code. |   and source code. | ||||||
|  |  | ||||||
|   curl is developed by a community, with Daniel at the wheel. |   curl is developed by a community, with Daniel at the wheel. | ||||||
|  |  | ||||||
|   1.6 What do you get for making cURL? |   1.6 What do you get for making cURL? | ||||||
|  |  | ||||||
|   Project cURL is entirely free and open, without any commercial interests or |   Project cURL is entirely free and open. No person gets paid in any way for | ||||||
|   money involved. No person gets paid in any way for developing curl. We all |   developing curl. We all do this voluntarily on our spare time. | ||||||
|   do this voluntarily on our spare time. |  | ||||||
|  |  | ||||||
|   We get some help from companies. Contactor Data hosts the curl web site and |   We get some help from companies. Contactor Data hosts the curl web site and | ||||||
|   the main mailing list, Haxx owns the curl web site's domain and |   the main mailing list, Haxx owns the curl web site's domain and | ||||||
|   sourceforge.net hosts several project tools we take advantage from like the |   sourceforge.net hosts several project tools we take advantage from like the | ||||||
|   bug tracker, mailing lists and more. |   bug tracker, mailing lists and more. | ||||||
|  |  | ||||||
|   If you feel you want to show support our project with a donation, a very |   If you want to support our project with a donation or similar, one way of | ||||||
|   nice way of doing that would be to buy "gift certificates" at useful online |   doing that would be to buy "gift certificates" at useful online shopping | ||||||
|   shopping sites, such as amazon.com or thinkgeek.com. |   sites, such as amazon.com or thinkgeek.com. Another way would be to sponsor | ||||||
|  |   us through a banner-program or by simply helping us coding, documenting, | ||||||
|  |   testing etc. | ||||||
|  |  | ||||||
|   1.7 What about CURL from curl.com? |   1.7 What about CURL from curl.com? | ||||||
|  |  | ||||||
| @@ -332,11 +334,12 @@ FAQ | |||||||
|  |  | ||||||
|      curl -L http://redirector.com |      curl -L http://redirector.com | ||||||
|  |  | ||||||
|   3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java? |   3.9 How do I use curl in my favourite programming language? | ||||||
|  |  | ||||||
|   There exist many language-interfaces for curl that integrates it better with |   There exist many language interfaces/bindings for curl that integrates it | ||||||
|   various languages. If you are fluid in a script language, you may very well |   better with various languages. If you are fluid in a script language, you | ||||||
|   opt to use such an interface instead of using the command line tool. |   may very well opt to use such an interface instead of using the command line | ||||||
|  |   tool. | ||||||
|  |  | ||||||
|   At the time of writing, there are bindings for the five language mentioned |   At the time of writing, there are bindings for the five language mentioned | ||||||
|   above, but chances are there are even more by the time you read this. Or you |   above, but chances are there are even more by the time you read this. Or you | ||||||
| @@ -347,16 +350,9 @@ FAQ | |||||||
|  |  | ||||||
|         http://curl.haxx.se/libcurl/ |         http://curl.haxx.se/libcurl/ | ||||||
|  |  | ||||||
|   PHP4 has the ability to use libcurl as an internal module if built with that |   In December 2001, there are interfaces available for the following | ||||||
|   option enabled. You then get a set of extra functions that can be used |   languages: C/C++, Cocoa, Dylan, Java, Perl, PHP, Python, Rexx, Ruby, Scheme | ||||||
|   within your PHP programs. You find all details about those functions in the |   and Tcl. By the time you read this, additional ones may have appeared! | ||||||
|   curl section in the PHP manual, see the online version at: |  | ||||||
|  |  | ||||||
|         http://www.php.net/manual/ref.curl.php |  | ||||||
|  |  | ||||||
|   PHP also offers the option to run a command line, and then you can of course |  | ||||||
|   invoke the curl tool using a command line. This is the way to use curl if |  | ||||||
|   you're using PHP3 or PHP4 built without curl module support. |  | ||||||
|  |  | ||||||
|   3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? |   3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? | ||||||
|  |  | ||||||
| @@ -383,8 +379,8 @@ FAQ | |||||||
|   etc. |   etc. | ||||||
|  |  | ||||||
|   There is one exception to this rule, and that is if you can "tunnel through" |   There is one exception to this rule, and that is if you can "tunnel through" | ||||||
|   the given HTTP proxy. Proxy tunneling is enabled with a special option (-P) |   the given HTTP proxy. Proxy tunneling is enabled with a special option (-p) | ||||||
|   and is generally not available as proxy admins usuable disable tunneling to |   and is generally not available as proxy admins usually disable tunneling to | ||||||
|   other ports than 443 (which is used for HTTPS access through proxies). |   other ports than 443 (which is used for HTTPS access through proxies). | ||||||
|  |  | ||||||
| 4. Running Problems | 4. Running Problems | ||||||
| @@ -476,11 +472,22 @@ FAQ | |||||||
|     identified by the Request-URI. The response MUST include an Allow header |     identified by the Request-URI. The response MUST include an Allow header | ||||||
|     containing a list of valid methods for the requested resource. |     containing a list of valid methods for the requested resource. | ||||||
|  |  | ||||||
|  |     4.5.6 "301 Moved Permanently" | ||||||
|  |   | ||||||
|  |     If you get this return code and an HTML outpt similar to this: | ||||||
|  |  | ||||||
|  |        <H1>Moved Permanently</H1> The document has moved <A | ||||||
|  |        HREF="http://same_url_now_with_a_trailing_slash/">here</A>. | ||||||
|  |  | ||||||
|  |     it might be because you request a directory URL but without the trailing | ||||||
|  |     slash. Try the same operation again _with_ the trailing URL, or use the | ||||||
|  |     -L/--location option to follow the redirection. | ||||||
|  |  | ||||||
|   4.6. Can you tell me what error code 142 means? |   4.6. Can you tell me what error code 142 means? | ||||||
|  |  | ||||||
|   All error codes that are larger than the highest documented error code means |   All error codes that are larger than the highest documented error code means | ||||||
|   that curl has exited due to a crash. This is a serious error, and we |   that curl has exited due to a crash. This is a serious error, and we | ||||||
|   appriciate a detailed bug report from you that describes how we could go |   appreciate a detailed bug report from you that describes how we could go | ||||||
|   ahead and repeat this! |   ahead and repeat this! | ||||||
|  |  | ||||||
|   4.7. How do I keep user names and passwords secret in Curl command lines? |   4.7. How do I keep user names and passwords secret in Curl command lines? | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ FTP | |||||||
|  - download |  - download | ||||||
|  - authentication |  - authentication | ||||||
|  - kerberos security |  - kerberos security | ||||||
|  - PORT or PASV |  - active/passive using PORT, EPRT, PASV or EPSV | ||||||
|  - single file size information (compare to HTTP HEAD) |  - single file size information (compare to HTTP HEAD) | ||||||
|  - 'type=' URL support |  - 'type=' URL support | ||||||
|  - dir listing |  - dir listing | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								docs/INSTALL
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								docs/INSTALL
									
									
									
									
									
								
							| @@ -36,8 +36,7 @@ UNIX | |||||||
|    The configure script always tries to find a working SSL library unless |    The configure script always tries to find a working SSL library unless | ||||||
|    explicitly told not to. If you have OpenSSL installed in the default search |    explicitly told not to. If you have OpenSSL installed in the default search | ||||||
|    path for your compiler/linker, you don't need to do anything special. If |    path for your compiler/linker, you don't need to do anything special. If | ||||||
|    you have OpenSSL installed in e.g /usr/local/ssl, you can run configure |    you have OpenSSL installed in /usr/local/ssl, you can run configure like: | ||||||
|    like: |  | ||||||
|  |  | ||||||
| 	./configure --with-ssl | 	./configure --with-ssl | ||||||
|  |  | ||||||
| @@ -46,13 +45,13 @@ UNIX | |||||||
|  |  | ||||||
| 	./configure --with-ssl=/opt/OpenSSL | 	./configure --with-ssl=/opt/OpenSSL | ||||||
|  |  | ||||||
|    If you insist on forcing a build *without* SSL support, even though you may |    If you insist on forcing a build without SSL support, even though you may | ||||||
|    have it installed in your system, you can run configure like this: |    have OpenSSL installed in your system, you can run configure like this: | ||||||
|  |  | ||||||
|         ./configure --without-ssl |         ./configure --without-ssl | ||||||
|  |  | ||||||
|    If you have OpenSSL installed, but with the libraries in one place and the |    If you have OpenSSL installed, but with the libraries in one place and the | ||||||
|    header files somewhere else, you'll have to set the LDFLAGS and CPPFLAGS |    header files somewhere else, you have to set the LDFLAGS and CPPFLAGS | ||||||
|    environment variables prior to running configure.  Something like this |    environment variables prior to running configure.  Something like this | ||||||
|    should work: |    should work: | ||||||
|  |  | ||||||
| @@ -72,7 +71,7 @@ UNIX | |||||||
|      LIBS=-lRSAglue -lrsaref |      LIBS=-lRSAglue -lrsaref | ||||||
|      (as suggested by Doug Kaufman) |      (as suggested by Doug Kaufman) | ||||||
|  |  | ||||||
|    KNOWN PROBLEMS |    KNOWN PROBLEMS (these ones should not happen anymore) | ||||||
|  |  | ||||||
|      If you happen to have autoconf installed, but a version older than 2.12 |      If you happen to have autoconf installed, but a version older than 2.12 | ||||||
|      you will get into trouble. Then you can still build curl by issuing these |      you will get into trouble. Then you can still build curl by issuing these | ||||||
| @@ -101,8 +100,8 @@ UNIX | |||||||
|  |  | ||||||
|    MORE OPTIONS |    MORE OPTIONS | ||||||
|  |  | ||||||
|      Remember, to force configure to use the standard cc compiler if both |      To force configure to use the standard cc compiler if both cc and gcc are | ||||||
|      cc and gcc are present, run configure like |      present, run configure like | ||||||
|  |  | ||||||
|        CC=cc ./configure |        CC=cc ./configure | ||||||
|          or |          or | ||||||
| @@ -130,11 +129,6 @@ UNIX | |||||||
|  |  | ||||||
|        ./configure --with-krb4=/usr/athena |        ./configure --with-krb4=/usr/athena | ||||||
|  |  | ||||||
|      If your system support shared libraries, but you want to built a static |  | ||||||
|      version only, you can disable building the shared version by using: |  | ||||||
|  |  | ||||||
|        ./configure --disable-shared |  | ||||||
|  |  | ||||||
|      If you're a curl developer and use gcc, you might want to enable more |      If you're a curl developer and use gcc, you might want to enable more | ||||||
|      debug options with the --enable-debug option. |      debug options with the --enable-debug option. | ||||||
|  |  | ||||||
| @@ -177,9 +171,9 @@ Win32 | |||||||
|         Make the sources in the src/ drawer be a "win32 console application" |         Make the sources in the src/ drawer be a "win32 console application" | ||||||
|         project. Name it curl. |         project. Name it curl. | ||||||
|  |  | ||||||
|         With VC++, add 'wsock32.lib' to the link libs when you build curl! |         With VC++, add 'ws2_32.lib' to the link libs when you build curl! | ||||||
|         Borland seems to do that itself magically. Of course you have to |         Borland seems to do that itself magically. Of course you have to make | ||||||
|         make sure it links with the libcurl too! |         sure it links with the libcurl too! | ||||||
|  |  | ||||||
|         For VC++ 6, there's an included Makefile.vc6 that should be possible |         For VC++ 6, there's an included Makefile.vc6 that should be possible | ||||||
|         to use out-of-the-box. |         to use out-of-the-box. | ||||||
| @@ -209,15 +203,32 @@ Win32 | |||||||
|       ---------------------------- |       ---------------------------- | ||||||
|         Please read the OpenSSL documentation on how to compile and install |         Please read the OpenSSL documentation on how to compile and install | ||||||
|         the OpenSSL library.  This generates the libeay32.dll and ssleay32.dll |         the OpenSSL library.  This generates the libeay32.dll and ssleay32.dll | ||||||
|         files. |         files in the out32dll subdirectory in the OpenSSL home directory.  If | ||||||
|  |         you compiled OpenSSL static libraries (libeay32.lib, ssleay32.lib, | ||||||
|  |         RSAglue.lib) they are created in the out32 subdirectory. | ||||||
|  |  | ||||||
|         Run the 'vcvars32.bat' file to get the proper environment variables |         Run the 'vcvars32.bat' file to get the proper environment variables | ||||||
|         set. Edit the makefile.vc6 in the lib directory and define |         set. The vcvars32.bat file is part of the Microsoft development | ||||||
|         OPENSSL_PATH.  Set the location of the OpenSSL library and run 'nmake |         environment and you may find it in 'C:\Program Files\Microsoft Visual | ||||||
|         vc-ssl' in the root directory. |         Studio\vc98\bin' if you installed Visual C/C++ 6 in the default | ||||||
|  |         directory. | ||||||
|  |  | ||||||
|         The vcvars32.bat file is part of the Microsoft development |         Before running nmake define the OPENSSL_PATH environment variable with | ||||||
|         environment. |         the root/base directory of OpenSSL, for example: | ||||||
|  |  | ||||||
|  |           set OPENSSL_PATH=c:\openssl-0.9.6b | ||||||
|  |  | ||||||
|  |         Then run 'nmake vc-ssl' or 'nmake vc-ssl-dll' in the curl's root | ||||||
|  |         directory.  'nmake vc-ssl' will create a libcurl static and dynamic | ||||||
|  |         libraries in the lib subdirectory, as well as a statically linked | ||||||
|  |         version of curl.exe in the scr subdirectory.  This statically linked | ||||||
|  |         version is a standalone executable not requiring any DLL at | ||||||
|  |         runtime. This making method requires that you have build the static | ||||||
|  |         libraries of OpenSSL available in OpenSSL's out32 subdirectory. | ||||||
|  | 	'nmake vc-ssl-dll' creates the libcurl dynamic library and | ||||||
|  | 	links curl.exe against libcurl and OpenSSL dynamically. | ||||||
|  | 	This executables requires libcurl.dll and the OpenSSL DLLs | ||||||
|  | 	at runtime. | ||||||
|  |  | ||||||
|       Microsoft / Borland style |       Microsoft / Borland style | ||||||
|       ------------------------- |       ------------------------- | ||||||
| @@ -328,6 +339,20 @@ VMS | |||||||
|    13-jul-2001 |    13-jul-2001 | ||||||
|    N. Baggus |    N. Baggus | ||||||
|  |  | ||||||
|  | QNX | ||||||
|  | === | ||||||
|  |    (This section was graciously brought to us by David Bentham) | ||||||
|  |  | ||||||
|  |    As QNX is targetted for resource constrained environments, the QNX headers | ||||||
|  |    set conservative limits. This includes the FD_SETSIZE macro, set by default | ||||||
|  |    to 32. Socket descriptors returned within the CURL library may exceed this, | ||||||
|  |    resulting in memory faults/SIGSEGV crashes when passed into select(..) | ||||||
|  |    calls using fd_set macros. | ||||||
|  |  | ||||||
|  |    A good all-round solution to this is to override the default when building | ||||||
|  |    libcurl, by overriding CFLAGS during configure, example | ||||||
|  |    #  configure CFLAGS='-DFD_SETSIZE=64 -g -O2' | ||||||
|  |  | ||||||
| CROSS COMPILE | CROSS COMPILE | ||||||
| ============= | ============= | ||||||
|  |  | ||||||
| @@ -370,7 +395,8 @@ CROSS COMPILE | |||||||
| PORTS | PORTS | ||||||
| ===== | ===== | ||||||
|    This is a probably incomplete list of known hardware and operating systems |    This is a probably incomplete list of known hardware and operating systems | ||||||
|    that curl has been compiled for: |    that curl has been compiled for. If you know one system curl compiles and | ||||||
|  |    runs on, that isn't listed, please let us know! | ||||||
|  |  | ||||||
|         - Alpha DEC OSF 4 |         - Alpha DEC OSF 4 | ||||||
|         - Alpha Digital UNIX v3.2 |         - Alpha Digital UNIX v3.2 | ||||||
| @@ -379,10 +405,13 @@ PORTS | |||||||
|         - Alpha OpenVMS V7.1-1H2 |         - Alpha OpenVMS V7.1-1H2 | ||||||
|         - Alpha Tru64 v5.0 5.1 |         - Alpha Tru64 v5.0 5.1 | ||||||
|         - HP-PA HP-UX 9.X 10.X 11.X |         - HP-PA HP-UX 9.X 10.X 11.X | ||||||
|  |         - HP-PA Linux | ||||||
|         - MIPS IRIX 6.2, 6.5 |         - MIPS IRIX 6.2, 6.5 | ||||||
|  |         - MIPS Linux | ||||||
|         - Power AIX 4.2, 4.3.1, 4.3.2 |         - Power AIX 4.2, 4.3.1, 4.3.2 | ||||||
|         - PowerPC Darwin 1.0 |         - PowerPC Darwin 1.0 | ||||||
|         - PowerPC Linux |         - PowerPC Linux | ||||||
|  |         - PowerPC Mac OS 9 | ||||||
|         - PowerPC Mac OS X |         - PowerPC Mac OS X | ||||||
|         - SINIX-Z v5 |         - SINIX-Z v5 | ||||||
|         - Sparc Linux |         - Sparc Linux | ||||||
| @@ -394,6 +423,7 @@ PORTS | |||||||
|         - Ultrix 4.3a |         - Ultrix 4.3a | ||||||
|         - i386 BeOS |         - i386 BeOS | ||||||
|         - i386 FreeBSD |         - i386 FreeBSD | ||||||
|  |         - i386 HURD | ||||||
|         - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4 |         - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4 | ||||||
|         - i386 NetBSD |         - i386 NetBSD | ||||||
|         - i386 OS/2 |         - i386 OS/2 | ||||||
| @@ -403,6 +433,7 @@ PORTS | |||||||
|         - i386 Windows 95, 98, ME, NT, 2000 |         - i386 Windows 95, 98, ME, NT, 2000 | ||||||
|         - ia64 Linux 2.3.99 |         - ia64 Linux 2.3.99 | ||||||
|         - m68k AmigaOS 3 |         - m68k AmigaOS 3 | ||||||
|  |         - m68k Linux | ||||||
|         - m68k OpenBSD |         - m68k OpenBSD | ||||||
|         - s390 Linux  |         - s390 Linux  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								docs/MANUAL
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								docs/MANUAL
									
									
									
									
									
								
							| @@ -601,15 +601,15 @@ RESUMING FILE TRANSFERS | |||||||
|  |  | ||||||
|  Continue downloading a document: |  Continue downloading a document: | ||||||
|  |  | ||||||
|         curl -c -o file ftp://ftp.server.com/path/file |         curl -C - -o file ftp://ftp.server.com/path/file | ||||||
|  |  | ||||||
|  Continue uploading a document(*1): |  Continue uploading a document(*1): | ||||||
|  |  | ||||||
|         curl -c -T file ftp://ftp.server.com/path/file |         curl -C - -T file ftp://ftp.server.com/path/file | ||||||
|  |  | ||||||
|  Continue downloading a document from a web server(*2): |  Continue downloading a document from a web server(*2): | ||||||
|  |  | ||||||
|         curl -c -o file http://www.server.com/ |         curl -C - -o file http://www.server.com/ | ||||||
|  |  | ||||||
|  (*1) = This requires that the ftp server supports the non-standard command |  (*1) = This requires that the ftp server supports the non-standard command | ||||||
|         SIZE. If it doesn't, curl will say so. |         SIZE. If it doesn't, curl will say so. | ||||||
| @@ -668,8 +668,14 @@ LDAP | |||||||
|   and offer ldap:// support. |   and offer ldap:// support. | ||||||
|  |  | ||||||
|   LDAP is a complex thing and writing an LDAP query is not an easy task. I do |   LDAP is a complex thing and writing an LDAP query is not an easy task. I do | ||||||
|   advice you to dig up the syntax description for that elsewhere, RFC 1959 if |   advice you to dig up the syntax description for that elsewhere. Two places | ||||||
|   no other place is better. |   that might suit you are: | ||||||
|  |  | ||||||
|  |   Netscape's "Netscape Directory SDK 3.0 for C Programmer's Guide Chapter 10: | ||||||
|  |   Working with LDAP URLs": | ||||||
|  |   http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm | ||||||
|  |  | ||||||
|  |   RFC 2255, "The LDAP URL Format" http://www.rfc-editor.org/rfc/rfc2255.txt | ||||||
|  |  | ||||||
|   To show you an example, this is now I can get all people from my local LDAP |   To show you an example, this is now I can get all people from my local LDAP | ||||||
|   server that has a certain sub-domain in their email address: |   server that has a certain sub-domain in their email address: | ||||||
|   | |||||||
| @@ -56,12 +56,13 @@ HTMLPAGES = \ | |||||||
| 	curl_mprintf.html \ | 	curl_mprintf.html \ | ||||||
| 	curl_global_init.html \ | 	curl_global_init.html \ | ||||||
| 	curl_global_cleanup.html \ | 	curl_global_cleanup.html \ | ||||||
| 	libcurl.html | 	libcurl.html \ | ||||||
|  | 	index.html | ||||||
|  |  | ||||||
| EXTRA_DIST = $(man_MANS) \ | EXTRA_DIST = $(man_MANS) \ | ||||||
| 	MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \ | 	MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \ | ||||||
| 	README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \ | 	README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \ | ||||||
| 	$(HTMLPAGES) | 	VERSIONS $(HTMLPAGES) | ||||||
|  |  | ||||||
| MAN2HTML= gnroff -man $< | man2html >$@ | MAN2HTML= gnroff -man $< | man2html >$@ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,18 +12,11 @@ README.win32 | |||||||
|   systems. While not being the main develop target, a fair share of curl users |   systems. While not being the main develop target, a fair share of curl users | ||||||
|   are win32-based. |   are win32-based. | ||||||
|  |  | ||||||
|   Some documentation in this archive will be tricky to read for Windows |   The unix-style man pages are tricky to read on windows, so therefore are all | ||||||
|   people, as they come in unix-style man pages. You can either download a |   those pages also converted to HTML and those are also included in the | ||||||
|   freely available nroff binary for win32 (*pointers appriciated*), convert |   release archives. | ||||||
|   the files into plain-text on your neighbor's unix machine or run over to the |  | ||||||
|   curl web site and view them as plain HTML. |  | ||||||
|  |  | ||||||
|   The main curl.1 man page is "built-in". Use a command line similar to this |   The main curl.1 man page is also "built-in" in the command line tool. Use a | ||||||
|   in order to extract a separate text file: |   command line similar to this in order to extract a separate text file: | ||||||
|  |  | ||||||
|         curl -M >manual.txt |         curl -M >manual.txt | ||||||
|  |  | ||||||
|   Download all the libcurl man pages in HTML format using the link on the |  | ||||||
|   bottom of this page: |  | ||||||
|  |  | ||||||
|         http://curl.haxx.se/libcurl/c/ |  | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ that have contributed with non-trivial parts: | |||||||
|  - Albert Chin-A-Young <china@thewrittenword.com> |  - Albert Chin-A-Young <china@thewrittenword.com> | ||||||
|  - Stephen Kick <skick@epicrealm.com> |  - Stephen Kick <skick@epicrealm.com> | ||||||
|  - Martin Hedenfalk <mhe@stacken.kth.se> |  - Martin Hedenfalk <mhe@stacken.kth.se> | ||||||
|  - Richard Prescott |  - Richard Prescott <rip at step.polymtl.ca> | ||||||
|  - Jason S. Priebe <priebe@wral-tv.com> |  - Jason S. Priebe <priebe@wral-tv.com> | ||||||
|  - T. Bharath <TBharath@responsenetworks.com> |  - T. Bharath <TBharath@responsenetworks.com> | ||||||
|  - Alexander Kourakos <awk@users.sourceforge.net> |  - Alexander Kourakos <awk@users.sourceforge.net> | ||||||
| @@ -75,3 +75,7 @@ that have contributed with non-trivial parts: | |||||||
|  - Andrew Francis <locust@familyhealth.com.au> |  - Andrew Francis <locust@familyhealth.com.au> | ||||||
|  - Tomasz Lacki <Tomasz.Lacki@primark.pl> |  - Tomasz Lacki <Tomasz.Lacki@primark.pl> | ||||||
|  - Georg Huettenegger <georg@ist.org> |  - Georg Huettenegger <georg@ist.org> | ||||||
|  |  - John Lask <johnlask@hotmail.com> | ||||||
|  |  - Eric Lavigne <erlavigne@wanadoo.fr> | ||||||
|  |  - Marcus Webster <marcus.webster@phocis.com> | ||||||
|  |  - G<>tz Babin-Ebell <babin<69>ebell@trustcenter.de> | ||||||
|   | |||||||
							
								
								
									
										128
									
								
								docs/TODO
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								docs/TODO
									
									
									
									
									
								
							| @@ -19,10 +19,7 @@ TODO | |||||||
|  |  | ||||||
|  * The new 'multi' interface is being designed. Work out the details, start |  * The new 'multi' interface is being designed. Work out the details, start | ||||||
|    implementing and write test applications! |    implementing and write test applications! | ||||||
|    [http://curl.haxx.se/dev/multi.h] |    [http://curl.haxx.se/lxr/source/lib/multi.h] | ||||||
|  |  | ||||||
|  * Add a name resolve cache to libcurl to make repeated fetches to the same |  | ||||||
|    host name (when persitancy isn't available) faster. |  | ||||||
|  |  | ||||||
|  * Introduce another callback interface for upload/download that makes one |  * Introduce another callback interface for upload/download that makes one | ||||||
|    less copy of data and thus a faster operation. |    less copy of data and thus a faster operation. | ||||||
| @@ -33,11 +30,36 @@ TODO | |||||||
|    telnet, ldap, dict or file. |    telnet, ldap, dict or file. | ||||||
|  |  | ||||||
|  * Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt |  * Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt | ||||||
|  |    This should be made to work on most of the supported platforms, or | ||||||
|  |    otherwise it isn't really interesting. | ||||||
|  |  | ||||||
|  |  * Data sharing. Tell which easy handles within a multi handle that should | ||||||
|  |    share cookies, connection cache, dns cache, ssl session cache. | ||||||
|  |  | ||||||
|  |  * Mutexes. By adding mutex callback support, the 'data sharing' mentioned | ||||||
|  |    above can be made between several easy handles running in different threads | ||||||
|  |    too. The actual mutex implementations will be left for the application to | ||||||
|  |    implement, libcurl will merely call 'getmutex' and 'leavemutex' callbacks. | ||||||
|  |  | ||||||
|  |  * No-faster-then-this transfers. Many people have limited bandwidth and they | ||||||
|  |    want the ability to make sure their transfers never use more bandwith than | ||||||
|  |    they think is good. | ||||||
|  |  | ||||||
|  |  * Set the SO_KEEPALIVE socket option to make libcurl notice and disconnect | ||||||
|  |    very long time idle connections. | ||||||
|  |  | ||||||
|  |  * Make sure we don't ever loop because of non-blocking sockets return | ||||||
|  |    EWOULDBLOCK or similar. This concerns the HTTP request sending (and | ||||||
|  |    especially regular HTTP POST), the FTP command sending etc. | ||||||
|  |  | ||||||
|  |  * Go through the code and verify that libcurl deals with big files >2GB and | ||||||
|  |    >4GB all over. Bug reports indicate that it doesn't currently work | ||||||
|  |    properly. | ||||||
|  |  | ||||||
|  DOCUMENTATION |  DOCUMENTATION | ||||||
|  |  | ||||||
|  * Document all CURLcode error codes, why they happen and what most likely |  * Document all CURLcode error codes, why they happen and what most likely | ||||||
|    will make them not happen again. |    will make them not happen again. In a libcurl point of view. | ||||||
|  |  | ||||||
|  FTP |  FTP | ||||||
|  |  | ||||||
| @@ -52,14 +74,7 @@ TODO | |||||||
|    already working http dito works. It of course requires that 'MDTM' works, |    already working http dito works. It of course requires that 'MDTM' works, | ||||||
|    and it isn't a standard FTP command. |    and it isn't a standard FTP command. | ||||||
|  |  | ||||||
|  * Suggested on the mailing list: CURLOPT_FTP_MKDIR...! |  * Add FTPS support with SSL for the data connection too. | ||||||
|  |  | ||||||
|  * Always use the FTP SIZE command before downloading, as that makes it more |  | ||||||
|    likely that we know the size when downloading. Some sites support SIZE but |  | ||||||
|    don't show the size in the RETR response! |  | ||||||
|  |  | ||||||
|  * Make FTP PASV work with IPv6 support. RFC 2428 "FTP Extensions for IPv6 and |  | ||||||
|    NATs" is interesting. |  | ||||||
|  |  | ||||||
|  HTTP |  HTTP | ||||||
|  |  | ||||||
| @@ -68,6 +83,12 @@ TODO | |||||||
|    encoding. [http://curl.haxx.se/dev/HTTP-PUT-stdin.txt] When the filter |    encoding. [http://curl.haxx.se/dev/HTTP-PUT-stdin.txt] When the filter | ||||||
|    system mentioned above gets real, it'll be a piece of cake to add. |    system mentioned above gets real, it'll be a piece of cake to add. | ||||||
|  |  | ||||||
|  |  * Pass a list of host name to libcurl to which we allow the user name and | ||||||
|  |    password to get sent to. Currently, it only get sent to the host name that | ||||||
|  |    the first URL uses (to prevent others from being able to read it), but this | ||||||
|  |    also prevents the authentication info from getting sent when following | ||||||
|  |    locations to legitimate other host names. | ||||||
|  |  | ||||||
|  * "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get |  * "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get | ||||||
|    and decode compressed documents. There is the zlib that is pretty good at |    and decode compressed documents. There is the zlib that is pretty good at | ||||||
|    decompressing stuff. This work was started in October 1999 but halted again |    decompressing stuff. This work was started in October 1999 but halted again | ||||||
| @@ -84,23 +105,55 @@ TODO | |||||||
|    http://www.innovation.ch/java/ntlm.html that contains detailed reverse- |    http://www.innovation.ch/java/ntlm.html that contains detailed reverse- | ||||||
|    engineered info. |    engineered info. | ||||||
|  |  | ||||||
|  * RFC2617 compliance, "Digest Access Authentication" |  * RFC2617 compliance, "Digest Access Authentication" A valid test page seem | ||||||
|    A valid test page seem to exist at: |    to exist at: http://hopf.math.nwu.edu/testpage/digest/ And some friendly | ||||||
|    http://hopf.math.nwu.edu/testpage/digest/ |    person's server source code is available at | ||||||
|    And some friendly person's server source code is available at |    http://hopf.math.nwu.edu/digestauth/index.html Then there's the Apache | ||||||
|    http://hopf.math.nwu.edu/digestauth/index.html |    mod_digest source code too of course.  It seems as if Netscape doesn't | ||||||
|    Then there's the Apache mod_digest source code too of course.  It seems as |    support this, and not many servers do. Although this is a lot better | ||||||
|    if Netscape doesn't support this, and not many servers do. Although this is |    authentication method than the more common "Basic". Basic sends the | ||||||
|    a lot better authentication method than the more common "Basic". Basic |    password in cleartext over the network, this "Digest" method uses a | ||||||
|    sends the password in cleartext over the network, this "Digest" method uses |    challange-response protocol which increases security quite a lot. | ||||||
|    a challange-response protocol which increases security quite a lot. |  | ||||||
|  |  * Pipelining. Sending multiple requests before the previous one(s) are done. | ||||||
|  |    This could possibly be implemented using the multi interface to queue | ||||||
|  |    requests and the response data. | ||||||
|  |  | ||||||
|  TELNET |  TELNET | ||||||
|  |  | ||||||
|  * Make TELNET work on windows98! |  * Make TELNET work on windows98! | ||||||
|  |  | ||||||
|  |  * 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. | ||||||
|  |  | ||||||
|  |  * 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 | ||||||
|  |    work for telnet. | ||||||
|  |  | ||||||
|  SSL |  SSL | ||||||
|  |  | ||||||
|  |  * If you really want to improve the SSL situation, you should probably have a | ||||||
|  |    look at SSL cafile loading as well - 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). Even better would be to support the SSL | ||||||
|  |    CAdir option - instead of loading all of the root CA certs for every | ||||||
|  |    request, this option allows you to only read the CA chain that is actually | ||||||
|  |    required (into the cache)... | ||||||
|  |  | ||||||
|  |  * Add an interface to libcurl that enables "session IDs" to get | ||||||
|  |    exported/imported. Cris Bailiff said: "OpenSSL has functions which can | ||||||
|  |    serialise the current SSL state to a buffer of your choice, and | ||||||
|  |    recover/reset the state from such a buffer at a later date - this is used | ||||||
|  |    by mod_ssl for apache to implement and SSL session ID cache". This whole | ||||||
|  |    idea might become moot if we enable the 'data sharing' as mentioned in the | ||||||
|  |    LIBCURL label above. | ||||||
|  |  | ||||||
|  |  * OpenSSL supports a callback for customised verification of the peer | ||||||
|  |    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 | ||||||
|  |    Clark) | ||||||
|  |  | ||||||
|  * Make curl's SSL layer option capable of using other free SSL libraries. |  * Make curl's SSL layer option capable of using other free SSL libraries. | ||||||
|    Such as the Mozilla Security Services |    Such as the Mozilla Security Services | ||||||
|    (http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS |    (http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS | ||||||
| @@ -108,7 +161,34 @@ TODO | |||||||
|  |  | ||||||
|  LDAP |  LDAP | ||||||
|  |  | ||||||
|  * Multiple URL requests don't work. [http://sourceforge.net/tracker/index.php?func=detail&aid=475407&group_id=976&atid=100976] |  * Look over the implementation. The looping will have to "go away" from the | ||||||
|  |    lib/ldap.c source file and get moved to the main network code so that the | ||||||
|  |    multi interface and friends will work for LDAP as well. | ||||||
|  |  | ||||||
|  |  CLIENT | ||||||
|  |  | ||||||
|  |  * "curl ftp://site.com/*.txt" | ||||||
|  |  | ||||||
|  |  * Several URLs can be specified to get downloaded. We should be able to use | ||||||
|  |    the same syntax to specify several files to get uploaded (using the same | ||||||
|  |    persistant connection), using -T. | ||||||
|  |  | ||||||
|  |  * When the multi interface has been implemented and proved to work, the | ||||||
|  |    client could be told to use maximum N simultaneous transfers and then just | ||||||
|  |    make sure that happens. It should of course not make more than one | ||||||
|  |    connection to the same remote host. | ||||||
|  |  | ||||||
|  |  * Extending the capabilities of the multipart formposting. How about leaving | ||||||
|  |    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 | ||||||
|  |    fil1.hdr contains extra headers like | ||||||
|  |  | ||||||
|  |      Content-Type: text/plain; charset=KOI8-R" | ||||||
|  |      Content-Transfer-Encoding: base64 | ||||||
|  |      X-User-Comment: Please don't use browser specific HTML code | ||||||
|  |  | ||||||
|  |    which should overwrite the program reasonable defaults (plain/text, | ||||||
|  |    8bit...) (Idea brough to us by kromJx) | ||||||
|  |  | ||||||
|  TEST SUITE |  TEST SUITE | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										64
									
								
								docs/VERSIONS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								docs/VERSIONS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  |                                   _   _ ____  _      | ||||||
|  |                               ___| | | |  _ \| |     | ||||||
|  |                              / __| | | | |_) | |     | ||||||
|  |                             | (__| |_| |  _ <| |___  | ||||||
|  |                              \___|\___/|_| \_\_____| | ||||||
|  |  | ||||||
|  | Version Numbers and Releases | ||||||
|  |  | ||||||
|  |  Curl is not only curl. Curl is also libcurl. They're actually individually | ||||||
|  |  versioned, but they mostly follow each other rather closely. | ||||||
|  |  | ||||||
|  |  The version numbering is always built up using the same system: | ||||||
|  |  | ||||||
|  |         X.Y[.Z][-preN] | ||||||
|  |  | ||||||
|  |  Where | ||||||
|  |    X is main version number | ||||||
|  |    Y is release number | ||||||
|  |    Z is patch number | ||||||
|  |    N is pre-release number | ||||||
|  |  | ||||||
|  |  One of these numbers will get bumped in each new release. The numbers to the | ||||||
|  |  right of a bumped number will be reset to zero. If Z is zero, it is not | ||||||
|  |  included in the version number. The pre release number is only included in | ||||||
|  |  pre releases (they're never used in public, official, releases). | ||||||
|  |  | ||||||
|  |  The main version number will get bumped when *really* big, world colliding | ||||||
|  |  changes are made. The release number is bumped when big changes are | ||||||
|  |  performed. The patch number is bumped when the changes are mere bugfixes and | ||||||
|  |  only minor feature changes. The pre-release is a counter, to identify which | ||||||
|  |  pre-release a certain release is. | ||||||
|  |  | ||||||
|  |  When reaching the end of a pre-release period, the version without the | ||||||
|  |  pre-release part will be released as a public release. | ||||||
|  |  | ||||||
|  |  It means that after release 1.2.3, we can release 2.0 if something really big | ||||||
|  |  has been made, 1.3 if not that big changes were made or 1.2.4 if mostly bugs | ||||||
|  |  were fixed. Before 1.2.4 is released, we might release a 1.2.4-pre1 release | ||||||
|  |  for the brave people to try before the actual release. | ||||||
|  |  | ||||||
|  |  Bumping, as in increasing the number with 1, is unconditionally only | ||||||
|  |  affecting one of the numbers (except the ones to the right of it, that may be | ||||||
|  |  set to zero). 1 becomes 2, 3 becomes 4, 9 becomes 10, 88 becomes 89 and 99 | ||||||
|  |  becomes 100. So, after 1.2.9 comes 1.2.10. After 3.99.3, 3.100 might come. | ||||||
|  |  | ||||||
|  |  All original curl source release archives are named according to the libcurl | ||||||
|  |  version (not according to the curl client version that, as said before, might | ||||||
|  |  differ). | ||||||
|  |  | ||||||
|  |  As a service to any application that might want to support new libcurl | ||||||
|  |  features while still being able to build with older versions, all releases | ||||||
|  |  have the libcurl version stored in the curl/curl.h file using a static | ||||||
|  |  numbering scheme that can be used for comparison. The version number is | ||||||
|  |  defined as: | ||||||
|  |          | ||||||
|  |         #define LIBCURL_VERSION_NUM 0xXXYYZZ | ||||||
|  |  | ||||||
|  |  Where XX, YY and ZZ are the main version, release and patch numbers in | ||||||
|  |  hexadecimal. All three numbers are always represented using two digits.  1.2 | ||||||
|  |  would appear as "0x010200" while version 9.11.7 appears as "0x090b07". | ||||||
|  |  | ||||||
|  |  This 6-digit hexadecimal number does not show pre-release number, and it is | ||||||
|  |  always a greater number in a more recent release. It makes comparisons with | ||||||
|  |  greater than and less than work. | ||||||
| @@ -2,7 +2,7 @@ | |||||||
| .\" nroff -man curl-config.1 | .\" nroff -man curl-config.1 | ||||||
| .\" Written by Daniel Stenberg | .\" Written by Daniel Stenberg | ||||||
| .\" | .\" | ||||||
| .TH curl-config 1 "16 August 2001" "Curl 7.8.1" "curl-config manual" | .TH curl-config 1 "21 January 2002" "Curl 7.9.3" "curl-config manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl-config \- Get information about a libcurl installation | curl-config \- Get information about a libcurl installation | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -11,6 +11,8 @@ curl-config \- Get information about a libcurl installation | |||||||
| .B curl-config | .B curl-config | ||||||
| displays information about a previous curl and libcurl installation. | displays information about a previous curl and libcurl installation. | ||||||
| .SH OPTIONS | .SH OPTIONS | ||||||
|  | .IP "--cc" | ||||||
|  | Displays the compiler used to build libcurl. | ||||||
| .IP "--cflags" | .IP "--cflags" | ||||||
| Set of compiler options (CFLAGS) to use when compiling files that use | Set of compiler options (CFLAGS) to use when compiling files that use | ||||||
| libcurl. Currently that is only thw include path to the curl include files. | libcurl. Currently that is only thw include path to the curl include files. | ||||||
| @@ -38,18 +40,23 @@ major, minor, patch. So that libcurl 7.7.4 would appear as 070704 and libcurl | |||||||
| .SH "EXAMPLES" | .SH "EXAMPLES" | ||||||
| What linker options do I need when I link with libcurl? | What linker options do I need when I link with libcurl? | ||||||
|  |  | ||||||
|   curl-config --libs |   $ curl-config --libs | ||||||
|  |  | ||||||
| What compiler options do I need when I compile using libcurl functions? | What compiler options do I need when I compile using libcurl functions? | ||||||
|  |  | ||||||
|   curl-config --cflags |   $ curl-config --cflags | ||||||
|  |  | ||||||
| How do I know if libcurl was built with SSL support? | How do I know if libcurl was built with SSL support? | ||||||
|  |  | ||||||
|   curl-config --feature | grep SSL |   $ curl-config --feature | grep SSL | ||||||
|  |  | ||||||
| What's the installed libcurl version? | What's the installed libcurl version? | ||||||
|  |  | ||||||
|   curl-config --version |   $ curl-config --version | ||||||
|  |  | ||||||
|  | How do I build a single file with a one-line command? | ||||||
|  |  | ||||||
|  |   $ `curl-config --cc --cflags --libs` -o example example.c | ||||||
|  |  | ||||||
| .SH "SEE ALSO" | .SH "SEE ALSO" | ||||||
| .BR curl (1) | .BR curl (1) | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								docs/curl.1
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								docs/curl.1
									
									
									
									
									
								
							| @@ -2,10 +2,9 @@ | |||||||
| .\" nroff -man curl.1 | .\" nroff -man curl.1 | ||||||
| .\" Written by Daniel Stenberg | .\" Written by Daniel Stenberg | ||||||
| .\" | .\" | ||||||
| .TH curl 1 "30 Oct 2001" "Curl 7.9.1" "Curl Manual" | .TH curl 1 "30 Nov 2001" "Curl 7.9.2" "Curl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or | curl \- transfer a URL | ||||||
| HTTPS syntax. |  | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| .B curl [options] | .B curl [options] | ||||||
| .I [URL...] | .I [URL...] | ||||||
| @@ -117,13 +116,13 @@ be written to stdout. (Option added in curl 7.9) | |||||||
| If this option is used several times, the last specfied file name will be | If this option is used several times, the last specfied file name will be | ||||||
| used. | used. | ||||||
| .IP "-C/--continue-at <offset>" | .IP "-C/--continue-at <offset>" | ||||||
| Continue/Resume a previous file transfer at the given offset. The | Continue/Resume a previous file transfer at the given offset. The given offset | ||||||
| given offset is the exact number of bytes that will be skipped | is the exact number of bytes that will be skipped counted from the beginning | ||||||
| counted from the beginning of the source file before it is transfered | of the source file before it is transfered to the destination.  If used with | ||||||
| to the destination. | uploads, the ftp server command SIZE will not be used by curl. | ||||||
| If used with uploads, the ftp server command SIZE will not be used by |  | ||||||
| curl. Upload resume is for FTP only. | Use "-C -" to tell curl to automatically find out where/how to resume the | ||||||
| HTTP resume is only possible with HTTP/1.1 or later servers. | transfer. It then uses the given output/input files to figure that out. | ||||||
|  |  | ||||||
| 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 "-d/--data <data>" | .IP "-d/--data <data>" | ||||||
| @@ -161,10 +160,14 @@ using this option the entire context of the posted data is kept as-is. If you | |||||||
| want to post a binary file without the strip-newlines feature of the | want to post a binary file without the strip-newlines feature of the | ||||||
| --data-ascii option, this is for you. | --data-ascii option, this is for you. | ||||||
|  |  | ||||||
| If this option is used several times, the last one will be used. |  | ||||||
|  |  | ||||||
| If this option is used several times, the ones following the first will | If this option is used several times, the ones following the first will | ||||||
| append data. | append data. | ||||||
|  | .IP "--disable-epsv" | ||||||
|  | (FTP) Tell curl to disable the use of the EPSV command when doing passive FTP | ||||||
|  | downloads. Curl will normally always first attempt to use EPSV before PASV, | ||||||
|  | but with this option, it will not try using EPSV. | ||||||
|  |  | ||||||
|  | IF this option is used several times, each occurrence will toggle this on/off. | ||||||
| .IP "-D/--dump-header <file>" | .IP "-D/--dump-header <file>" | ||||||
| (HTTP/FTP) | (HTTP/FTP) | ||||||
| Write the HTTP headers to this file. Write the FTP file info to this | Write the HTTP headers to this file. Write the FTP file info to this | ||||||
| @@ -507,7 +510,7 @@ password is specified, curl will ask for it interactively. | |||||||
|  |  | ||||||
| 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 "--url <URL>" | .IP "--url <URL>" | ||||||
| Specify a URL to fetch. This option is mostly handy when you wanna specify | Specify a URL to fetch. This option is mostly handy when you want to specify | ||||||
| URL(s) in a config file. | URL(s) in a config file. | ||||||
|  |  | ||||||
| This option may be used any number of times. To control where this URL is written, use the | This option may be used any number of times. To control where this URL is written, use the | ||||||
| @@ -535,7 +538,7 @@ write "@-". | |||||||
| The variables present in the output format will be substituted by the value or | The variables present in the output format will be substituted by the value or | ||||||
| text that curl thinks fit, as described below. All variables are specified | text that curl thinks fit, as described below. All variables are specified | ||||||
| like %{variable_name} and to output a normal % you just write them like | like %{variable_name} and to output a normal % you just write them like | ||||||
| %%. You can output a newline by using \\n, a carrige return with \\r and a tab | %%. You can output a newline by using \\n, a carriage return with \\r and a tab | ||||||
| space with \\t. | space with \\t. | ||||||
|  |  | ||||||
| .B NOTE: | .B NOTE: | ||||||
| @@ -569,6 +572,11 @@ The time, in seconds, it took from the start until the file transfer is just | |||||||
| about to begin. This includes all pre-transfer commands and negotiations that | about to begin. This includes all pre-transfer commands and negotiations that | ||||||
| are specific to the particular protocol(s) involved. | are specific to the particular protocol(s) involved. | ||||||
| .TP | .TP | ||||||
|  | .B time_starttransfer | ||||||
|  | The time, in seconds, it took from the start until the first byte is just about | ||||||
|  | to be transfered. This includes time_pretransfer and also the time the | ||||||
|  | server needs to calculate the result. | ||||||
|  | .TP | ||||||
| .B size_download | .B size_download | ||||||
| The total amount of bytes that were downloaded. | The total amount of bytes that were downloaded. | ||||||
| .TP | .TP | ||||||
| @@ -668,7 +676,7 @@ If this option is used several times, the last one will be used. | |||||||
| Default config file. | Default config file. | ||||||
|  |  | ||||||
| .SH ENVIRONMENT | .SH ENVIRONMENT | ||||||
| .IP "HTTP_PROXY [protocol://]<host>[:port]" | .IP "http_proxy [protocol://]<host>[:port]" | ||||||
| Sets proxy server to use for HTTP. | Sets proxy server to use for HTTP. | ||||||
| .IP "HTTPS_PROXY [protocol://]<host>[:port]" | .IP "HTTPS_PROXY [protocol://]<host>[:port]" | ||||||
| Sets proxy server to use for HTTPS. | Sets proxy server to use for HTTPS. | ||||||
| @@ -679,11 +687,8 @@ Sets proxy server to use for GOPHER. | |||||||
| .IP "ALL_PROXY [protocol://]<host>[:port]" | .IP "ALL_PROXY [protocol://]<host>[:port]" | ||||||
| Sets proxy server to use if no protocol-specific proxy is set. | Sets proxy server to use if no protocol-specific proxy is set. | ||||||
| .IP "NO_PROXY <comma-separated list of hosts>" | .IP "NO_PROXY <comma-separated list of hosts>" | ||||||
| list of host names that shouldn't go through any proxy. If set to a | list of host names that shouldn't go through any proxy. If set to a asterisk | ||||||
| asterisk '*' only, it matches all hosts. | '*' only, it matches all hosts. | ||||||
| .IP "COLUMNS <integer>" |  | ||||||
| The width of the terminal.  This variable only affects curl when the |  | ||||||
| --progress-bar option is used. |  | ||||||
| .SH EXIT CODES | .SH EXIT CODES | ||||||
| There exists a bunch of different error codes and their corresponding error | There exists a bunch of different error codes and their corresponding error | ||||||
| messages that may appear during bad conditions. At the time of this writing, | messages that may appear during bad conditions. At the time of this writing, | ||||||
| @@ -783,13 +788,17 @@ Internal error. A function was called in a bad order. | |||||||
| .IP 45 | .IP 45 | ||||||
| Interface error. A specified outgoing interface could not be used. | Interface error. A specified outgoing interface could not be used. | ||||||
| .IP 46 | .IP 46 | ||||||
| Bad password entered. An error was signalled when the password was entered. | Bad password entered. An error was signaled when the password was entered. | ||||||
| .IP 47 | .IP 47 | ||||||
| Too many redirects. When following redirects, curl hit the maximum amount. | Too many redirects. When following redirects, curl hit the maximum amount. | ||||||
| .IP 48 | .IP 48 | ||||||
| Unknown TELNET option specified. | Unknown TELNET option specified. | ||||||
| .IP 49 | .IP 49 | ||||||
| Malformed telnet option. | Malformed telnet option. | ||||||
|  | .IP 51 | ||||||
|  | The remote peer's SSL certificate wasn't ok | ||||||
|  | .IP 52 | ||||||
|  | The server didn't reply anything, which here is considered an error. | ||||||
| .IP XX | .IP XX | ||||||
| There will appear more error codes here in future releases. The existing ones | There will appear more error codes here in future releases. The existing ones | ||||||
| are meant to never change. | are meant to never change. | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| .\" nroff -man [file] | .\" nroff -man [file] | ||||||
| .\" $Id$ | .\" $Id$ | ||||||
| .\" | .\" | ||||||
| .TH curl_easy_init 3 "5 March 2001" "libcurl 7.6.1" "libcurl Manual" | .TH curl_easy_init 3 "31 Jan 2001" "libcurl 7.9.4" "libcurl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl_easy_getinfo - Extract information from a curl session (added in 7.4) | curl_easy_getinfo - Extract information from a curl session (added in 7.4) | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -30,9 +30,11 @@ Pass a pointer to a long to receive the last received HTTP code. | |||||||
| .TP | .TP | ||||||
| .B CURLINFO_FILETIME | .B CURLINFO_FILETIME | ||||||
| Pass a pointer to a long to receive the remote time of the retrieved | Pass a pointer to a long to receive the remote time of the retrieved | ||||||
| document. If you get 0, it can be because of many reasons (unknown, the server | document. If you get -1, it can be because of many reasons (unknown, the | ||||||
| hides it or the server doesn't support the command that tells document time | server hides it or the server doesn't support the command that tells document | ||||||
| etc) and the time of the document is unknown. (Added in 7.5) | time etc) and the time of the document is unknown. Note that you must tell the | ||||||
|  | server to collect this information before the transfer is made, by using the | ||||||
|  | CURLOPT_FILETIME option to \fIcurl_easy_setopt(3)\fP. (Added in 7.5) | ||||||
| .TP | .TP | ||||||
| .B CURLINFO_TOTAL_TIME | .B CURLINFO_TOTAL_TIME | ||||||
| Pass a pointer to a double to receive the total transaction time in seconds | Pass a pointer to a double to receive the total transaction time in seconds | ||||||
| @@ -52,6 +54,12 @@ start until the file transfer is just about to begin. This includes all | |||||||
| pre-transfer commands and negotiations that are specific to the particular | pre-transfer commands and negotiations that are specific to the particular | ||||||
| protocol(s) involved. | protocol(s) involved. | ||||||
| .TP | .TP | ||||||
|  | .B CURLINFO_STARTTRANSFER_TIME | ||||||
|  | Pass a pointer to a double to receive the time, in seconds, it took from the | ||||||
|  | start until the first byte is just about to be transfered. This includes | ||||||
|  | CURLINFO_PRETRANSFER_TIME and also the time the server needs to calculate | ||||||
|  | the result. | ||||||
|  | .TP | ||||||
| .B CURLINFO_SIZE_UPLOAD | .B CURLINFO_SIZE_UPLOAD | ||||||
| Pass a pointer to a double to receive the total amount of bytes that were | Pass a pointer to a double to receive the total amount of bytes that were | ||||||
| uploaded. | uploaded. | ||||||
| @@ -89,6 +97,12 @@ is the value read from the Content-Length: field.  (Added in 7.6.1) | |||||||
| .B CURLINFO_CONTENT_LENGTH_UPLOAD | .B CURLINFO_CONTENT_LENGTH_UPLOAD | ||||||
| Pass a pointer to a double to receive the specified size of the upload. | Pass a pointer to a double to receive the specified size of the upload. | ||||||
| (Added in 7.6.1) | (Added in 7.6.1) | ||||||
|  | .TP | ||||||
|  | .B CURLINFO_CONTENT_TYPE | ||||||
|  | Pass a pointer to a 'char *' to receive the content-type of the downloaded | ||||||
|  | object. This is the value read from the Content-Type: field. If you get NULL, | ||||||
|  | it means that the server didn't send a valid Content-Type header or that the | ||||||
|  | protocol used doesn't support this.  (Added in 7.9.4) | ||||||
| .PP | .PP | ||||||
|  |  | ||||||
| .SH RETURN VALUE | .SH RETURN VALUE | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| .\" nroff -man [file] | .\" nroff -man [file] | ||||||
| .\" $Id$ | .\" $Id$ | ||||||
| .\" | .\" | ||||||
| .TH curl_easy_setopt 3 "11 Oct 2001" "libcurl 7.9.1" "libcurl Manual" | .TH curl_easy_setopt 3 "10 Dec 2001" "libcurl 7.9.2" "libcurl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl_easy_setopt - Set curl easy-session options | curl_easy_setopt - Set curl easy-session options | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -77,9 +77,8 @@ function gets called by libcurl as soon as it needs to read data in order to | |||||||
| send it to the peer. The data area pointed at by the pointer \fIptr\fP may be | send it to the peer. The data area pointed at by the pointer \fIptr\fP may be | ||||||
| filled with at most \fIsize\fP multiplied with \fInmemb\fP number of | filled with at most \fIsize\fP multiplied with \fInmemb\fP number of | ||||||
| bytes. Your function must return the actual number of bytes that you stored in | bytes. Your function must return the actual number of bytes that you stored in | ||||||
| that memory area. Returning -1 will signal an error to the library and cause | that memory area. Returning 0 will signal end-of-file to the library and cause | ||||||
| it to abort the current transfer immediately (with a \fICURLE_READ_ERROR\fP | it to stop the current transfer. | ||||||
| return code). |  | ||||||
| .TP | .TP | ||||||
| .B CURLOPT_INFILESIZE | .B CURLOPT_INFILESIZE | ||||||
| When uploading a file to a remote site, this option should be used to tell | When uploading a file to a remote site, this option should be used to tell | ||||||
| @@ -320,13 +319,59 @@ with \fIcurl_easy_cleanup(3)\fP. | |||||||
| .TP | .TP | ||||||
| .B CURLOPT_SSLCERT | .B CURLOPT_SSLCERT | ||||||
| Pass a pointer to a zero terminated string as parameter. The string should be | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
| the file name of your certificate in PEM format. | the file name of your certificate. The default format is "PEM" and can be | ||||||
|  | changed with \fICURLOPT_SSLCERTTYPE\fP. | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSLCERTTYPE | ||||||
|  | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
|  | the format of your certificate. Supported formats are "PEM" and "DER".  (Added | ||||||
|  | in 7.9.3) | ||||||
| .TP | .TP | ||||||
| .B CURLOPT_SSLCERTPASSWD | .B CURLOPT_SSLCERTPASSWD | ||||||
| Pass a pointer to a zero terminated string as parameter. It will be used as | Pass a pointer to a zero terminated string as parameter. It will be used as | ||||||
| the password required to use the CURLOPT_SSLCERT certificate. If the password | the password required to use the CURLOPT_SSLCERT certificate. If the password | ||||||
| is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can | is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can | ||||||
| be used to set your own prompt function. | be used to set your own prompt function. | ||||||
|  |  | ||||||
|  | \fBNOTE:\fPThis option is replaced by \fICURLOPT_SSLKEYPASSWD\fP and only | ||||||
|  | cept for backward compatibility. You never needed a pass phrase to load | ||||||
|  | a certificate but you need one to load your private key. | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSLKEY | ||||||
|  | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
|  | the file name of your private key. The default format is "PEM" and can be | ||||||
|  | changed with \fICURLOPT_SSLKEYTYPE\fP. (Added in 7.9.3) | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSLKEYTYPE | ||||||
|  | Pass a pointer to a zero terminated string as parameter. The string should be | ||||||
|  | the format of your private key. Supported formats are "PEM", "DER" and "ENG". | ||||||
|  | (Added in 7.9.3) | ||||||
|  |  | ||||||
|  | \fBNOTE:\fPThe format "ENG" enables you to load the private key from a crypto | ||||||
|  | engine. in this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to | ||||||
|  | the engine. You have to set the crypto engine with \fICURLOPT_SSL_ENGINE\fP. | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSLKEYASSWD | ||||||
|  | Pass a pointer to a zero terminated string as parameter. It will be used as | ||||||
|  | the password required to use the \fICURLOPT_SSLKEY\fP private key. If the | ||||||
|  | password is not supplied, you will be prompted for | ||||||
|  | it. \fICURLOPT_PASSWDFUNCTION\fP can be used to set your own prompt function. | ||||||
|  | (Added in 7.9.3) | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSL_ENGINE | ||||||
|  | Pass a pointer to a zero terminated string as parameter. It will be used as | ||||||
|  | the identifier for the crypto engine you want to use for your private | ||||||
|  | key. (Added in 7.9.3) | ||||||
|  |  | ||||||
|  | \fBNOTE:\fPIf the crypto device cannot be loaded, | ||||||
|  | \fICURLE_SSL_ENGINE_NOTFOUND\fP is returned. | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_SSL_ENGINEDEFAULT | ||||||
|  | Sets the actual crypto engine as the default for (asymetric) crypto | ||||||
|  | operations. (Added in 7.9.3) | ||||||
|  |  | ||||||
|  | \fBNOTE:\fPIf the crypto device cannot be set, | ||||||
|  | \fICURLE_SSL_ENGINE_SETFAILED\fP is returned. | ||||||
| .TP | .TP | ||||||
| .B CURLOPT_CRLF | .B CURLOPT_CRLF | ||||||
| Convert Unix newlines to CRLF newlines on FTP uploads. | Convert Unix newlines to CRLF newlines on FTP uploads. | ||||||
| @@ -336,13 +381,15 @@ Pass a pointer to a linked list of FTP commands to pass to the server prior to | |||||||
| your ftp request. The linked list should be a fully valid list of 'struct | your ftp request. The linked list should be a fully valid list of 'struct | ||||||
| curl_slist' structs properly filled in. Use \fIcurl_slist_append(3)\fP to | curl_slist' structs properly filled in. Use \fIcurl_slist_append(3)\fP to | ||||||
| append strings (commands) to the list, and clear the entire list afterwards | append strings (commands) to the list, and clear the entire list afterwards | ||||||
| with \fIcurl_slist_free_all(3)\fP. | with \fIcurl_slist_free_all(3)\fP. Disable this operation again by setting a | ||||||
|  | NULL to this option. | ||||||
| .TP | .TP | ||||||
| .B CURLOPT_POSTQUOTE | .B CURLOPT_POSTQUOTE | ||||||
| Pass a pointer to a linked list of FTP commands to pass to the server after | Pass a pointer to a linked list of FTP commands to pass to the server after | ||||||
| your ftp transfer request. The linked list should be a fully valid list of | your ftp transfer request. The linked list should be a fully valid list of | ||||||
| struct curl_slist structs properly filled in as described for | struct curl_slist structs properly filled in as described for | ||||||
| \fICURLOPT_QUOTE\fP. | \fICURLOPT_QUOTE\fP. Disable this operation again by setting a NULL to this | ||||||
|  | option. | ||||||
| .TP | .TP | ||||||
| .B CURLOPT_WRITEHEADER | .B CURLOPT_WRITEHEADER | ||||||
| Pass a pointer to be used to write the header part of the received data to. If | Pass a pointer to be used to write the header part of the received data to. If | ||||||
| @@ -545,6 +592,29 @@ compile OpenSSL. | |||||||
|  |  | ||||||
| You'll find more details about cipher lists on this URL: | You'll find more details about cipher lists on this URL: | ||||||
| \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP | \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_HTTP_VERSION | ||||||
|  | Pass a long, set to one of the values described below. They force libcurl to | ||||||
|  | use the specific HTTP versions. This is not sensible to do unless you have a | ||||||
|  | good reason. | ||||||
|  | .RS | ||||||
|  | .TP 5 | ||||||
|  | .B CURL_HTTP_VERSION_NONE | ||||||
|  | We don't care about what version the library uses. libcurl will use whatever | ||||||
|  | it thinks fit. | ||||||
|  | .TP | ||||||
|  | .B CURL_HTTP_VERSION_1_0 | ||||||
|  | Enforce HTTP 1.0 requests. | ||||||
|  | .TP | ||||||
|  | .B CURL_HTTP_VERSION_1_1 | ||||||
|  | Enforce HTTP 1.1 requests. | ||||||
|  | .RE | ||||||
|  | .TP | ||||||
|  | .B CURLOPT_FTP_USE_EPSV | ||||||
|  | Pass a long. If the value is non-zero, it tells curl to use the EPSV command | ||||||
|  | when doing passive FTP downloads (which is always does by default). Using EPSV | ||||||
|  | means that it will first attempt to use EPSV before using PASV, but if you | ||||||
|  | pass FALSE (zero) to this option, it will not try using EPSV, only plain PASV. | ||||||
| .PP | .PP | ||||||
| .SH RETURN VALUE | .SH RETURN VALUE | ||||||
| CURLE_OK (zero) means that the option was set properly, non-zero means an | CURLE_OK (zero) means that the option was set properly, non-zero means an | ||||||
|   | |||||||
| @@ -58,6 +58,13 @@ are allowed. The effect of this parameter is the same as giving multiple | |||||||
| \fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or | \fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or | ||||||
| before each \fBCURLFORM_FILE\fP option. | before each \fBCURLFORM_FILE\fP option. | ||||||
|  |  | ||||||
|  | Should you need to specify extra headers for the form POST section, use | ||||||
|  | \fBCURLFORM_CONTENTHEADER\fP. This takes a curl_slist prepared in the usual way | ||||||
|  | using \fBcurl_slist_append\fP and appends the list of headers to those Curl | ||||||
|  | automatically generates for \fBCURLFORM_CONTENTTYPE\fP and the content  | ||||||
|  | disposition. The list must exist while the POST occurs, if you free it before | ||||||
|  | the post completes you may experience problems. | ||||||
|  |  | ||||||
| The last argument in such an array must always be \fBCURLFORM_END\fP. | The last argument in such an array must always be \fBCURLFORM_END\fP. | ||||||
|  |  | ||||||
| The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to | The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| .\" nroff -man [file] | .\" nroff -man [file] | ||||||
| .\" $Id$ | .\" $Id$ | ||||||
| .\" | .\" | ||||||
| .TH curl_formparse 3 "21 May 2001" "libcurl 7.7.4" "libcurl Manual" | .TH curl_formparse 3 "17 Dec 2001" "libcurl 7.9.2" "libcurl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl_formparse - add a section to a multipart/formdata HTTP POST: | curl_formparse - add a section to a multipart/formdata HTTP POST: | ||||||
| deprecated (use curl_formadd instead) | deprecated (use curl_formadd instead) | ||||||
| @@ -13,75 +13,6 @@ deprecated (use curl_formadd instead) | |||||||
| .BI "struct HttpPost ** " lastitem ");" | .BI "struct HttpPost ** " lastitem ");" | ||||||
| .ad | .ad | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| curl_formparse() is used to append sections when building a multipart/formdata | This has been removed deliberately. The \fBcurl_formadd\fP has been introduced | ||||||
| HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at | to replace this function. Do not use this. Convert to the new function | ||||||
| a time until you've added all the sections you want included and then you pass | now. curl_formparse() will be removed from a future version of libcurl. | ||||||
| the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP. |  | ||||||
| \fIlastitem\fP is set after each call and on repeated invokes it should be |  | ||||||
| left as set to allow repeated invokes to find the end of the list in a faster |  | ||||||
| way.  \fIstring\fP must be a zero terminated string abiding to the syntax |  | ||||||
| described in a section below |  | ||||||
|  |  | ||||||
| The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to |  | ||||||
| NULL in the first call to this function. All list-data will be allocated by |  | ||||||
| the function itself. You must call \fIcurl_formfree\fP after the form post has |  | ||||||
| been done to free the resources again. |  | ||||||
|  |  | ||||||
| This function will copy all input data and keep its own version of it |  | ||||||
| allocated until you call \fIcurl_formfree\fP. When you've passed the pointer |  | ||||||
| to \fIcurl_easy_setopt\fP, you must not free the list until after you've |  | ||||||
| called \fIcurl_easy_cleanup\fP for the curl handle. |  | ||||||
|  |  | ||||||
| See example below. |  | ||||||
| .SH "FORM PARSE STRINGS" |  | ||||||
| The |  | ||||||
| .I string  |  | ||||||
| parameter must be using one of the following patterns. Note that the [] |  | ||||||
| letters should not be included in the real-life string. |  | ||||||
| .TP 0.8i |  | ||||||
| .B [name]=[contents] |  | ||||||
| Add a form field named 'name' with the contents 'contents'. This is the |  | ||||||
| typcial contents of the HTML tag <input type=text>. |  | ||||||
| .TP |  | ||||||
| .B [name]=@[filename] |  | ||||||
| Add a form field named 'name' with the contents as read from the local file |  | ||||||
| named 'filename'. This is the typcial contents of the HTML tag <input |  | ||||||
| type=file>. |  | ||||||
| .TP |  | ||||||
| .B [name]=@[filename1,filename2,...] |  | ||||||
| Add a form field named 'name' with the contents as read from the local files |  | ||||||
| named 'filename1' and 'filename2'. This is identical to the upper, except that |  | ||||||
| you get the contents of several files in one section. |  | ||||||
| .TP |  | ||||||
| .B [name]=@[filename];[type=<content-type>] |  | ||||||
| Whenever you specify a file to read from, you can optionally specify the |  | ||||||
| content-type as well. The content-type is passed to the server together with |  | ||||||
| the contents of the file. curl_formparse() will guess content-type for a |  | ||||||
| number of well-known extensions and otherwise it will set it to binary. You |  | ||||||
| can override the internal decision by using this option. |  | ||||||
| .TP |  | ||||||
| .B [name]=@[filename1,filename2,...];[type=<content-type>] |  | ||||||
| When you specify several files to read the contents from, you can set the |  | ||||||
| content-type for all of them in the same way as with a single file. |  | ||||||
| .PP |  | ||||||
| .SH RETURN VALUE |  | ||||||
| Returns non-zero if an error occurs. |  | ||||||
| .SH EXAMPLE |  | ||||||
|  |  | ||||||
|  HttpPost* post = NULL; |  | ||||||
|  HttpPost* last = NULL; |  | ||||||
|  |  | ||||||
|  /* Add an image section */ |  | ||||||
|  curl_formparse("picture=@my-face.jpg", &post, &last); |  | ||||||
|  /* Add a normal text section */ |  | ||||||
|  curl_formparse("name=FooBar", &post, &last); |  | ||||||
|  /* Set the form info */ |  | ||||||
|  curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); |  | ||||||
|  |  | ||||||
| .SH "SEE ALSO" |  | ||||||
| .BR curl_easy_setopt "(3), " |  | ||||||
| .BR curl_formadd "(3), " |  | ||||||
| .BR curl_formfree "(3) |  | ||||||
| .SH BUGS |  | ||||||
| Surely there are some, you tell me! |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| .\" nroff -man [file] | .\" nroff -man [file] | ||||||
| .\" $Id$ | .\" $Id$ | ||||||
| .\" | .\" | ||||||
| .TH curl_global_init 3 "14 August 2001" "libcurl 7.8.1" "libcurl Manual" | .TH curl_global_init 3 "13 Nov 2001" "libcurl 7.9.1" "libcurl Manual" | ||||||
| .SH NAME | .SH NAME | ||||||
| curl_global_init - Global libcurl initialisation | curl_global_init - Global libcurl initialisation | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| @@ -11,8 +11,8 @@ curl_global_init - Global libcurl initialisation | |||||||
| .BI "CURLcode curl_global_init(long " flags ");" | .BI "CURLcode curl_global_init(long " flags ");" | ||||||
| .ad | .ad | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| This function should be called once (no matter how many threads or libcurl | This function should only be called once (no matter how many threads or | ||||||
| sessions that'll be used) by every application that uses libcurl. | libcurl sessions that'll be used) by every application that uses libcurl. | ||||||
|  |  | ||||||
| If this function hasn't been invoked when \fIcurl_easy_init\fP is called, it | If this function hasn't been invoked when \fIcurl_easy_init\fP is called, it | ||||||
| will be done automatically by libcurl. | will be done automatically by libcurl. | ||||||
| @@ -23,6 +23,8 @@ init, as described below. Set the desired bits by ORing the values together. | |||||||
| You must however \fBalways\fP use the \fIcurl_global_cleanup\fP function, as | You must however \fBalways\fP use the \fIcurl_global_cleanup\fP function, as | ||||||
| that cannot be called automatically for you by libcurl. | that cannot be called automatically for you by libcurl. | ||||||
|  |  | ||||||
|  | Calling this function more than once will cause unpredictable results. | ||||||
|  |  | ||||||
| This function was added in libcurl 7.8. | This function was added in libcurl 7.8. | ||||||
| .SH FLAGS | .SH FLAGS | ||||||
| .TP 5 | .TP 5 | ||||||
|   | |||||||
| @@ -4,9 +4,10 @@ | |||||||
|  |  | ||||||
| AUTOMAKE_OPTIONS = foreign no-dependencies | AUTOMAKE_OPTIONS = foreign no-dependencies | ||||||
|  |  | ||||||
| EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \ | EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \ | ||||||
| 	     win32sockets.c persistant.c ftpget.c Makefile.example \ | 	     win32sockets.c persistant.c ftpget.c Makefile.example \ | ||||||
| 	     multithread.c getinmemory.c ftpupload.c httpput.c | 	     multithread.c getinmemory.c ftpupload.c httpput.c \ | ||||||
|  | 	     simplessl.c ftpgetresp.c http-post.c | ||||||
|  |  | ||||||
| all: | all: | ||||||
| 	@echo "done" | 	@echo "done" | ||||||
|   | |||||||
| @@ -10,6 +10,10 @@ them for submission in future packages and on the web site. | |||||||
| The Makefile.example is an example makefile that could be used to build these | The Makefile.example is an example makefile that could be used to build these | ||||||
| examples. Just edit the file according to your system and requirements first. | examples. Just edit the file according to your system and requirements first. | ||||||
|  |  | ||||||
|  | Most examples should build fine using a command line like this: | ||||||
|  |  | ||||||
|  |   $ gcc `curl-config --cflags` `curl-config --libs` -o example example.c | ||||||
|  |  | ||||||
| Try the php/examples/ directory for PHP programming snippets! | Try the php/examples/ directory for PHP programming snippets! | ||||||
|  |  | ||||||
|   *PLEASE* do not use the curl.haxx.se site as a test target for your libcurl |   *PLEASE* do not use the curl.haxx.se site as a test target for your libcurl | ||||||
|   | |||||||
| @@ -14,31 +14,70 @@ | |||||||
| #include <curl/types.h> | #include <curl/types.h> | ||||||
| #include <curl/easy.h> | #include <curl/easy.h> | ||||||
|  |  | ||||||
| /* to make this work under windows, use the win32-functions from the | /* | ||||||
|    win32socket.c file as well */ |  * This is an example showing how to get a single file from an FTP server. | ||||||
|  |  * It delays the actual destination file creation until the first write | ||||||
|  |  * callback so that it won't create an empty file in case the remote file | ||||||
|  |  * doesn't exist or something else fails. | ||||||
|  |  */ | ||||||
|  |  | ||||||
| int main(int argc, char **argv) | struct FtpFile { | ||||||
|  |   char *filename; | ||||||
|  |   FILE *stream; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) | ||||||
|  | { | ||||||
|  |   struct FtpFile *out=(struct FtpFile *)stream; | ||||||
|  |   if(out && !out->stream) { | ||||||
|  |     /* open file for writing */ | ||||||
|  |     out->stream=fopen(out->filename, "wb"); | ||||||
|  |     if(!out->stream) | ||||||
|  |       return -1; /* failure, can't open file to write */ | ||||||
|  |   } | ||||||
|  |   return fwrite(buffer, size, nmemb, out->stream); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int main(void) | ||||||
| { | { | ||||||
|   CURL *curl; |   CURL *curl; | ||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   FILE *ftpfile; |   struct FtpFile ftpfile={ | ||||||
|  |     "curl.tar.gz", /* name to store the file as if succesful */ | ||||||
|  |     NULL | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   /* local file name to store the file as */ |   curl_global_init(CURL_GLOBAL_DEFAULT); | ||||||
|   ftpfile = fopen("curl.tar.gz", "wb"); /* b is binary for win */ |  | ||||||
|    |    | ||||||
|   curl = curl_easy_init(); |   curl = curl_easy_init(); | ||||||
|   if(curl) { |   if(curl) { | ||||||
|     /* Get curl 7.7 from sunet.se's FTP site: */ |     /* Get curl 7.9.2 from sunet.se's FTP site: */ | ||||||
|     curl_easy_setopt(curl, CURLOPT_URL, |     curl_easy_setopt(curl, CURLOPT_URL, | ||||||
|                      "ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.7.tar.gz"); |                      "ftp://ftp.sunet.se/pub/www/utilities/curl/curl-7.9.2.tar.gz"); | ||||||
|     curl_easy_setopt(curl, CURLOPT_FILE, ftpfile); |     /* Define our callback to get called when there's data to be written */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); | ||||||
|  |     /* Set a pointer to our struct to pass to the callback */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile); | ||||||
|  |  | ||||||
|  |     /* Switch on full protocol/debug output */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); | ||||||
|  |  | ||||||
|     res = curl_easy_perform(curl); |     res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|     /* always cleanup */ |     /* always cleanup */ | ||||||
|     curl_easy_cleanup(curl); |     curl_easy_cleanup(curl); | ||||||
|  |  | ||||||
|  |     if(CURLE_OK != res) { | ||||||
|  |       /* we failed */ | ||||||
|  |       fprintf(stderr, "curl told us %d\n", res); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   fclose(ftpfile); /* close the local file */ |   if(ftpfile.stream) | ||||||
|  |     fclose(ftpfile.stream); /* close the local file */ | ||||||
|  |  | ||||||
|  |   curl_global_cleanup(); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								docs/examples/ftpgetresp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								docs/examples/ftpgetresp.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include <curl/curl.h> | ||||||
|  | #include <curl/types.h> | ||||||
|  | #include <curl/easy.h> | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Similar to ftpget.c but this also stores the received response-lines | ||||||
|  |  * in a separate file using our own callback! | ||||||
|  |  * | ||||||
|  |  * This functionality was introduced in libcurl 7.9.3. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | size_t | ||||||
|  | write_response(void *ptr, size_t size, size_t nmemb, void *data) | ||||||
|  | { | ||||||
|  |   FILE *writehere = (FILE *)data; | ||||||
|  |   return fwrite(ptr, size, nmemb, writehere); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |   CURL *curl; | ||||||
|  |   CURLcode res; | ||||||
|  |   FILE *ftpfile; | ||||||
|  |   FILE *respfile; | ||||||
|  |    | ||||||
|  |   /* local file name to store the file as */ | ||||||
|  |   ftpfile = fopen("ftp-list", "wb"); /* b is binary, needed on win32 */ | ||||||
|  |  | ||||||
|  |   /* local file name to store the FTP server's response lines in */ | ||||||
|  |   respfile = fopen("ftp-responses", "wb"); /* b is binary, needed on win32 */ | ||||||
|  |  | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if(curl) { | ||||||
|  |     /* Get a file listing from sunet */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.sunet.se/"); | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_FILE, ftpfile); | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response); | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile); | ||||||
|  |     res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|  |     /* always cleanup */ | ||||||
|  |     curl_easy_cleanup(curl); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   fclose(ftpfile); /* close the local file */ | ||||||
|  |   fclose(respfile); /* close the response file */ | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								docs/examples/http-post.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								docs/examples/http-post.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  |   CURL *curl; | ||||||
|  |   CURLcode res; | ||||||
|  |  | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if(curl) { | ||||||
|  |     /* First set the URL that is about to receive our POST. This URL can | ||||||
|  |        just as well be a https:// URL if that is what should receive the | ||||||
|  |        data. */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi"); | ||||||
|  |     /* Now specify the POST data */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl"); | ||||||
|  |  | ||||||
|  |     /* Perform the request, res will get the return code */ | ||||||
|  |     res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|  |     /* always cleanup */ | ||||||
|  |     curl_easy_cleanup(curl); | ||||||
|  |   } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
| @@ -1,71 +0,0 @@ | |||||||
| /***************************************************************************** |  | ||||||
|  *                                  _   _ ____  _      |  | ||||||
|  *  Project                     ___| | | |  _ \| |     |  | ||||||
|  *                             / __| | | | |_) | |     |  | ||||||
|  *                            | (__| |_| |  _ <| |___  |  | ||||||
|  *                             \___|\___/|_| \_\_____| |  | ||||||
|  * |  | ||||||
|  * $Id$ |  | ||||||
|  * |  | ||||||
|  * Example code that uploads a file name 'foo' to a remote script that accepts |  | ||||||
|  * "HTML form based" (as described in RFC1738) uploads using HTTP POST. |  | ||||||
|  * |  | ||||||
|  * The imaginary form we'll fill in looks like: |  | ||||||
|  * |  | ||||||
|  * <form method="post" enctype="multipart/form-data" action="examplepost.cgi"> |  | ||||||
|  * Enter file: <input type="file" name="sendfile" size="40"> |  | ||||||
|  * Enter file name: <input type="text" name="filename" size="30"> |  | ||||||
|  * <input type="submit" value="send" name="submit"> |  | ||||||
|  * </form> |  | ||||||
|  * |  | ||||||
|  * This exact source code has not been verified to work. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* to make this work under windows, use the win32-functions from the |  | ||||||
|    win32socket.c file as well */ |  | ||||||
|  |  | ||||||
| #include <stdio.h> |  | ||||||
|  |  | ||||||
| #include <curl/curl.h> |  | ||||||
| #include <curl/types.h> |  | ||||||
| #include <curl/easy.h> |  | ||||||
|  |  | ||||||
| int main(int argc, char **argv) |  | ||||||
| { |  | ||||||
|   CURL *curl; |  | ||||||
|   CURLcode res; |  | ||||||
|  |  | ||||||
|   struct HttpPost *formpost=NULL; |  | ||||||
|   struct HttpPost *lastptr=NULL; |  | ||||||
|  |  | ||||||
|   /* Fill in the file upload field */ |  | ||||||
|   curl_formparse("sendfile=@foo", |  | ||||||
|                  &formpost, |  | ||||||
|                  &lastptr); |  | ||||||
|  |  | ||||||
|   /* Fill in the filename field */ |  | ||||||
|   curl_formparse("filename=foo", |  | ||||||
|                  &formpost, |  | ||||||
|                  &lastptr); |  | ||||||
|    |  | ||||||
|  |  | ||||||
|   /* Fill in the submit field too, even if this is rarely needed */ |  | ||||||
|   curl_formparse("submit=send", |  | ||||||
|                  &formpost, |  | ||||||
|                  &lastptr); |  | ||||||
|  |  | ||||||
|   curl = curl_easy_init(); |  | ||||||
|   if(curl) { |  | ||||||
|     /* what URL that receives this POST */ |  | ||||||
|     curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi"); |  | ||||||
|     curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |  | ||||||
|     res = curl_easy_perform(curl); |  | ||||||
|  |  | ||||||
|     /* always cleanup */ |  | ||||||
|     curl_easy_cleanup(curl); |  | ||||||
|  |  | ||||||
|     /* then cleanup the formpost chain */ |  | ||||||
|     curl_formfree(formpost); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| @@ -9,27 +9,16 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  |  | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
| #include <curl/types.h> |  | ||||||
| #include <curl/easy.h> |  | ||||||
|  |  | ||||||
| /* to make this work under windows, use the win32-functions from the | int main(void) | ||||||
|    win32socket.c file as well */ |  | ||||||
|  |  | ||||||
| int main(int argc, char **argv) |  | ||||||
| { | { | ||||||
|   CURL *curl; |   CURL *curl; | ||||||
|   CURLcode res; |   CURLcode res; | ||||||
|   FILE *headerfile; |  | ||||||
|  |  | ||||||
|   headerfile = fopen("dumpit", "w"); |  | ||||||
|  |  | ||||||
|   curl = curl_easy_init(); |   curl = curl_easy_init(); | ||||||
|   if(curl) { |   if(curl) { | ||||||
|     /* what call to write: */ |  | ||||||
|     curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se"); |     curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se"); | ||||||
|     curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile); |  | ||||||
|     res = curl_easy_perform(curl); |     res = curl_easy_perform(curl); | ||||||
|  |  | ||||||
|     /* always cleanup */ |     /* always cleanup */ | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								docs/examples/simplessl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								docs/examples/simplessl.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include <curl/curl.h> | ||||||
|  | #include <curl/types.h> | ||||||
|  | #include <curl/easy.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* some requirements for this to work: | ||||||
|  |    1.   set pCertFile to the file with the client certificate | ||||||
|  |    2.   if the key is passphrase protected, set pPassphrase to the | ||||||
|  |         passphrase you use | ||||||
|  |    3.   if you are using a crypto engine: | ||||||
|  |    3.1. set a #define USE_ENGINE | ||||||
|  |    3.2. set pEngine to the name of the crypto engine you use | ||||||
|  |    3.3. set pKeyName to the key identifier you want to use | ||||||
|  |    4.   if you don't use a crypto engine: | ||||||
|  |    4.1. set pKeyName to the file name of your client key | ||||||
|  |    4.2. if the format of the key file is DER, set pKeyType to "DER" | ||||||
|  |  | ||||||
|  |    !! verify of the server certificate is not implemented here !! | ||||||
|  |  | ||||||
|  |    **** This example only works with libcurl 7.9.3 and later! **** | ||||||
|  |  | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | int main(int argc, char **argv) | ||||||
|  | { | ||||||
|  |   CURL *curl; | ||||||
|  |   CURLcode res; | ||||||
|  |   FILE *headerfile; | ||||||
|  |  | ||||||
|  |   const char *pCertFile = "testcert.pem"; | ||||||
|  |   const char *pCACertFile="cacert.pem" | ||||||
|  |  | ||||||
|  |   const char *pKeyName; | ||||||
|  |   const char *pKeyType; | ||||||
|  |  | ||||||
|  |   const char *pEngine; | ||||||
|  |  | ||||||
|  | #if USE_ENGINE | ||||||
|  |   pKeyName  = "rsa_test"; | ||||||
|  |   pKeyType  = "ENG"; | ||||||
|  |   pEngine   = "chil";            /* for nChiper HSM... */ | ||||||
|  | #else | ||||||
|  |   pKeyName  = "testkey.pem"; | ||||||
|  |   pKeyType  = "PEM"; | ||||||
|  |   pEngine   = NULL; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   const char *pPassphrase = NULL; | ||||||
|  |  | ||||||
|  |   headerfile = fopen("dumpit", "w"); | ||||||
|  |  | ||||||
|  |   curl_global_init(CURL_GLOBAL_DEFAULT); | ||||||
|  |  | ||||||
|  |   curl = curl_easy_init(); | ||||||
|  |   if(curl) { | ||||||
|  |     /* what call to write: */ | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_URL, "HTTPS://curl.haxx.se"); | ||||||
|  |     curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile); | ||||||
|  |  | ||||||
|  |     while(1)                    /* do some ugly short cut... */ | ||||||
|  |     { | ||||||
|  |        if (pEngine)             /* use crypto engine */ | ||||||
|  |        { | ||||||
|  |           if (curl_easy_setopt(curl, CURLOPT_SSLENGINE,pEngine) != CURLE_OK) | ||||||
|  |           {                     /* load the crypto engine */ | ||||||
|  |              fprintf(stderr,"can't set crypto engine\n"); | ||||||
|  |              break; | ||||||
|  |           } | ||||||
|  |           if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT,1) != CURLE_OK) | ||||||
|  |           {                     /* set the crypto engine as default */ | ||||||
|  |                                 /* only needed for the first time you load | ||||||
|  |                                    a engine in a curl object... */ | ||||||
|  |              fprintf(stderr,"can't set crypto engine as default\n"); | ||||||
|  |              break; | ||||||
|  |           } | ||||||
|  |        } | ||||||
|  |                                 /* cert is stored PEM coded in file... */ | ||||||
|  |                                 /* since PEM is default, we needn't set it for PEM */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM"); | ||||||
|  |                                 /* set the cert for client authentication */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_SSLCERT,pCertFile); | ||||||
|  |                                 /* sorry, for engine we must set the passphrase | ||||||
|  |                                    (if the key has one...) */ | ||||||
|  |        if (pPassphrase) | ||||||
|  |           curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,pPassphrase); | ||||||
|  |                                 /* if we use a key stored in a crypto engine, | ||||||
|  |                                    we must set the key type to "ENG" */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,pKeyType); | ||||||
|  |                                 /* set the private key (file or ID in engine) */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_SSLKEY,pKeyName); | ||||||
|  |                                 /* set the file with the certs vaildating the server */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_CAINFO,pCACertFile); | ||||||
|  |                                 /* disconnect if we can't validate server's cert */ | ||||||
|  |        curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1); | ||||||
|  |         | ||||||
|  |        res = curl_easy_perform(curl); | ||||||
|  |        break;                   /* we are done... */ | ||||||
|  |     } | ||||||
|  |     /* always cleanup */ | ||||||
|  |     curl_easy_cleanup(curl); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   curl_global_cleanup(); | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								docs/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								docs/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | HTML> | ||||||
|  | <HEAD> | ||||||
|  | <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> | ||||||
|  | <TITLE>Index to Curl documentation</TITLE> | ||||||
|  | </HEAD> | ||||||
|  |  | ||||||
|  | <BODY> | ||||||
|  | <H1 ALIGN="CENTER">Index to Curl documentation</H1> | ||||||
|  |  | ||||||
|  | <H2>Programs</H2> | ||||||
|  | <P><A HREF="curl-config.html">curl-config.html</A> | ||||||
|  | <P><A HREF="curl.html">curl.html</A> | ||||||
|  |  | ||||||
|  | <H2>Library routines</H2> | ||||||
|  | <P><A HREF="libcurl.html">libcurl.html</A> | ||||||
|  | <P><A HREF="curl_easy_cleanup.html">curl_easy_cleanup.html</A> | ||||||
|  | <P><A HREF="curl_easy_duphandle.html">curl_easy_duphandle.html</A> | ||||||
|  | <P><A HREF="curl_easy_getinfo.html">curl_easy_getinfo.html</A> | ||||||
|  | <P><A HREF="curl_easy_init.html">curl_easy_init.html</A> | ||||||
|  | <P><A HREF="curl_easy_perform.html">curl_easy_perform.html</A> | ||||||
|  | <P><A HREF="curl_easy_setopt.html">curl_easy_setopt.html</A> | ||||||
|  | <P><A HREF="curl_escape.html">curl_escape.html</A> | ||||||
|  | <P><A HREF="curl_formadd.html">curl_formadd.html</A> | ||||||
|  | <P><A HREF="curl_formfree.html">curl_formfree.html</A> | ||||||
|  | <P><A HREF="curl_formparse.html">curl_formparse.html</A> | ||||||
|  | <P><A HREF="curl_getdate.html">curl_getdate.html</A> | ||||||
|  | <P><A HREF="curl_getenv.html">curl_getenv.html</A> | ||||||
|  | <P><A HREF="curl_global_cleanup.html">curl_global_cleanup.html</A> | ||||||
|  | <P><A HREF="curl_global_init.html">curl_global_init.html</A> | ||||||
|  | <P><A HREF="curl_mprintf.html">curl_mprintf.html</A> | ||||||
|  | <P><A HREF="curl_slist_append.html">curl_slist_append.html</A> | ||||||
|  | <P><A HREF="curl_slist_free_all.html">curl_slist_free_all.html</A> | ||||||
|  | <P><A HREF="curl_strequal.html">curl_strequal.html</A> | ||||||
|  | <P><A HREF="curl_strnequal.html">curl_strnequal.html</A> | ||||||
|  | <P><A HREF="curl_unescape.html">curl_unescape.html</A> | ||||||
|  | <P><A HREF="curl_version.html">curl_version.html</A> | ||||||
|  | </BODY> | ||||||
|  | </HTML> | ||||||
							
								
								
									
										824
									
								
								docs/libcurl-the-guide
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										824
									
								
								docs/libcurl-the-guide
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,824 @@ | |||||||
|  | $Id$ | ||||||
|  |                                   _   _ ____  _      | ||||||
|  |                               ___| | | |  _ \| |     | ||||||
|  |                              / __| | | | |_) | |     | ||||||
|  |                             | (__| |_| |  _ <| |___  | ||||||
|  |                              \___|\___/|_| \_\_____| | ||||||
|  |  | ||||||
|  | PROGRAMMING WITH LIBCURL | ||||||
|  |  | ||||||
|  | About this Document | ||||||
|  |  | ||||||
|  |  This document will attempt to describe the general principle and some basic | ||||||
|  |  approaches to consider when programming with libcurl. The text will focus | ||||||
|  |  mainly on the C interface but might apply fairly well on other interfaces as | ||||||
|  |  well as they usually follow the C one pretty closely. | ||||||
|  |  | ||||||
|  |  This document will refer to 'the user' as the person writing the source code | ||||||
|  |  that uses libcurl. That would probably be you or someone in your position. | ||||||
|  |  What will be generally refered to as 'the program' will be the collected | ||||||
|  |  source code that you write that is using libcurl for transfers. The program | ||||||
|  |  is outside libcurl and libcurl is outside of the program. | ||||||
|  |  | ||||||
|  |  To get the more details on all options and functions described herein, please | ||||||
|  |  refer to their respective man pages. | ||||||
|  |  | ||||||
|  | Building | ||||||
|  |  | ||||||
|  |  There are many different ways to build C programs. This chapter will assume a | ||||||
|  |  unix-style build process. If you use a different build system, you can still | ||||||
|  |  read this to get general information that may apply to your environment as | ||||||
|  |  well. | ||||||
|  |  | ||||||
|  |   Compiling the Program | ||||||
|  |  | ||||||
|  |     Your compiler needs to know where the libcurl headers are | ||||||
|  |     located. Therefore you must set your compiler's include path to point to | ||||||
|  |     the directory where you installed them. The 'curl-config'[3] tool can be | ||||||
|  |     used to get this information: | ||||||
|  |  | ||||||
|  |         $ curl-config --cflags | ||||||
|  |  | ||||||
|  |   Linking the Program with libcurl | ||||||
|  |  | ||||||
|  |     When having compiled the program, you need to link your object files to | ||||||
|  |     create a single executable. For that to succeed, you need to link with | ||||||
|  |     libcurl and possibly also with other libraries that libcurl itself depends | ||||||
|  |     on. Like OpenSSL librararies, but even some standard OS libraries may be | ||||||
|  |     needed on the command line. To figure out which flags to use, once again | ||||||
|  |     the 'curl-config' tool comes to the rescue: | ||||||
|  |  | ||||||
|  |         $ curl-config --libs | ||||||
|  |  | ||||||
|  |   SSL or Not | ||||||
|  |  | ||||||
|  |     libcurl can be built and customized in many ways. One of the things that | ||||||
|  |     varies from different libraries and builds is the support for SSL-based | ||||||
|  |     transfers, like HTTPS and FTPS. If OpenSSL was detected properly at | ||||||
|  |     build-time, libcurl will be built with SSL support. To figure out if an | ||||||
|  |     installed libcurl has been built with SSL support enabled, use | ||||||
|  |     'curl-config' like this: | ||||||
|  |  | ||||||
|  |         $ curl-config --feature | ||||||
|  |  | ||||||
|  |     And if SSL is supported, the keyword 'SSL' will be written to stdout, | ||||||
|  |     possibly together with a few other features that can be on and off on | ||||||
|  |     different libcurls. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Portable Code in a Portable World | ||||||
|  |  | ||||||
|  |  The people behind libcurl have put a considerable effort to make libcurl work | ||||||
|  |  on a large amount of different operating systems and environments. | ||||||
|  |  | ||||||
|  |  You program libcurl the same way on all platforms that libcurl runs on. There | ||||||
|  |  are only very few minor considerations that differs. If you just make sure to | ||||||
|  |  write your code portable enough, you may very well create yourself a very | ||||||
|  |  portable program. libcurl shouldn't stop you from that. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Global Preparation | ||||||
|  |  | ||||||
|  |  The program must initialize some of the libcurl functionality globally. That | ||||||
|  |  means it should be done exactly once, no matter how many times you intend to | ||||||
|  |  use the library. Once for your program's entire life time. This is done using | ||||||
|  |  | ||||||
|  |     curl_global_init() | ||||||
|  |  | ||||||
|  |  and it takes one parameter which is a bit pattern that tells libcurl what to | ||||||
|  |  intialize. Using CURL_GLOBAL_ALL will make it initialize all known internal | ||||||
|  |  sub modules, and might be a good default option. The current two bits that | ||||||
|  |  are specified are: | ||||||
|  |  | ||||||
|  |   CURL_GLOBAL_WIN32 which only does anything on Windows machines. When used on | ||||||
|  |   a Windows machine, it'll make libcurl intialize the win32 socket | ||||||
|  |   stuff. Without having that initialized properly, your program cannot use | ||||||
|  |   sockets properly. You should only do this once for each application, so if | ||||||
|  |   your program already does this or of another library in use does it, you | ||||||
|  |   should not tell libcurl to do this as well. | ||||||
|  |  | ||||||
|  |   CURL_GLOBAL_SSL which only does anything on libcurls compiled and built | ||||||
|  |   SSL-enabled. On these systems, this will make libcurl init OpenSSL properly | ||||||
|  |   for this application. This is only needed to do once for each application so | ||||||
|  |   if your program or another library already does this, this bit should not be | ||||||
|  |   needed. | ||||||
|  |  | ||||||
|  |  libcurl has a default protection mechanism that detects if curl_global_init() | ||||||
|  |  hasn't been called by the time curl_easy_perform() is called and if that is | ||||||
|  |  the case, libcurl runs the function itself with a guessed bit pattern. Please | ||||||
|  |  note that depending solely on this is not considered nice nor very good. | ||||||
|  |  | ||||||
|  |  When the program no longer uses libcurl, it should call | ||||||
|  |  curl_global_cleanup(), which is the opposite of the init call. It will then | ||||||
|  |  do the reversed operations to cleanup the resources the curl_global_init() | ||||||
|  |  call initialized. | ||||||
|  |  | ||||||
|  |  Repeated calls to curl_global_init() and curl_global_cleanup() should be | ||||||
|  |  avoided. They should be called once each. | ||||||
|  |  | ||||||
|  | Handle the Easy libcurl | ||||||
|  |  | ||||||
|  |  libcurl version 7 is oriented around the so called easy interface. All | ||||||
|  |  operations in the easy interface are prefixed with 'curl_easy'. | ||||||
|  |  | ||||||
|  |  Future libcurls will also offer the multi interface. More about that | ||||||
|  |  interface, what it is targeted for and how to use it is still only debated on | ||||||
|  |  the libcurl mailing list and developer web pages. Join up to discuss and | ||||||
|  |  figure out! | ||||||
|  |  | ||||||
|  |  To use the easy interface, you must first create yourself an easy handle. You | ||||||
|  |  need one handle for each easy session you want to perform. Basicly, you | ||||||
|  |  should use one handle for every thread you plan to use for transferring. You | ||||||
|  |  must never share the same handle in multiple threads. | ||||||
|  |  | ||||||
|  |  Get an easy handle with | ||||||
|  |  | ||||||
|  |     easyhandle = curl_easy_init(); | ||||||
|  |  | ||||||
|  |  It returns an easy handle. Using that you proceed to the next step: setting | ||||||
|  |  up your preferred actions. A handle is just a logic entity for the upcoming | ||||||
|  |  transfer or series of transfers. | ||||||
|  |  | ||||||
|  |  You set properties and options for this handle using curl_easy_setopt(). They | ||||||
|  |  control how the subsequent transfer or transfers will be made. Options remain | ||||||
|  |  set in the handle until set again to something different. Alas, multiple | ||||||
|  |  requests using the same handle will use the same options. | ||||||
|  |  | ||||||
|  |  Many of the informationals you set in libcurl are "strings", pointers to data | ||||||
|  |  terminated with a zero byte. Keep in mind that when you set strings with | ||||||
|  |  curl_easy_setopt(), libcurl will not copy the data. It will merely point to | ||||||
|  |  the data. You MUST make sure that the data remains available for libcurl to | ||||||
|  |  use until finished or until you use the same option again to point to | ||||||
|  |  something else. | ||||||
|  |  | ||||||
|  |  One of the most basic properties to set in the handle is the URL. You set | ||||||
|  |  your preferred URL to transfer with CURLOPT_URL in a manner similar to: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/"); | ||||||
|  |  | ||||||
|  |  Let's assume for a while that you want to receive data as the URL indentifies | ||||||
|  |  a remote resource you want to get here. Since you write a sort of application | ||||||
|  |  that needs this transfer, I assume that you would like to get the data passed | ||||||
|  |  to you directly instead of simply getting it passed to stdout. So, you write | ||||||
|  |  your own function that matches this prototype: | ||||||
|  |  | ||||||
|  |     size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp); | ||||||
|  |  | ||||||
|  |  You tell libcurl to pass all data to this function by issuing a function | ||||||
|  |  similar to this: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data); | ||||||
|  |  | ||||||
|  |  You can control what data your function get in the forth argument by setting | ||||||
|  |  another property: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_FILE, &internal_struct); | ||||||
|  |  | ||||||
|  |  Using that property, you can easily pass local data between your application | ||||||
|  |  and the function that gets invoked by libcurl. libcurl itself won't touch the | ||||||
|  |  data you pass with CURLOPT_FILE. | ||||||
|  |  | ||||||
|  |  libcurl offers its own default internal callback that'll take care of the | ||||||
|  |  data if you don't set the callback with CURLOPT_WRITEFUNCTION. It will then | ||||||
|  |  simply output the received data to stdout. You can have the default callback | ||||||
|  |  write the data to a different file handle by passing a 'FILE *' to a file | ||||||
|  |  opened for writing with the CURLOPT_FILE option. | ||||||
|  |  | ||||||
|  |  Now, we need to take a step back and have a deep breath. Here's one of those | ||||||
|  |  rare platform-dependent nitpicks. Did you spot it? On some platforms[2], | ||||||
|  |  libcurl won't be able to operate on files opened by the program. Thus, if you | ||||||
|  |  use the default callback and pass in a an open file with CURLOPT_FILE, it | ||||||
|  |  will crash. You should therefore avoid this to make your program run fine | ||||||
|  |  virtually everywhere. | ||||||
|  |  | ||||||
|  |  There are of course many more options you can set, and we'll get back to a | ||||||
|  |  few of them later. Let's instead continue to the actual transfer: | ||||||
|  |  | ||||||
|  |     success = curl_easy_perform(easyhandle); | ||||||
|  |  | ||||||
|  |  The curl_easy_perform() will connect to the remote site, do the necessary | ||||||
|  |  commands and receive the transfer. Whenever it receives data, it calls the | ||||||
|  |  callback function we previously set. The function may get one byte at a time, | ||||||
|  |  or it may get many kilobytes at once. libcurl delivers as much as possible as | ||||||
|  |  often as possible. Your callback function should return the number of bytes | ||||||
|  |  it "took care of". If that is not the exact same amount of bytes that was | ||||||
|  |  passed to it, libcurl will abort the operation and return with an error code. | ||||||
|  |  | ||||||
|  |  When the transfer is complete, the function returns a return code that | ||||||
|  |  informs you if it succeeded in its mission or not. If a return code isn't | ||||||
|  |  enough for you, you can use the CURLOPT_ERRORBUFFER to point libcurl to a | ||||||
|  |  buffer of yours where it'll store a human readable error message as well. | ||||||
|  |  | ||||||
|  |  If you then want to transfer another file, the handle is ready to be used | ||||||
|  |  again. Mind you, it is even preferred that you re-use an existing handle if | ||||||
|  |  you intend to make another transfer. libcurl will then attempt to re-use the | ||||||
|  |  previous | ||||||
|  |  | ||||||
|  |  | ||||||
|  | When It Doesn't Work | ||||||
|  |  | ||||||
|  |  There will always be times when the transfer fails for some reason. You might | ||||||
|  |  have set the wrong libcurl option or misunderstood what the libcurl option | ||||||
|  |  actually does, or the remote server might return non-standard replies that | ||||||
|  |  confuse the library which then confuses your program. | ||||||
|  |  | ||||||
|  |  There's one golden rule when these things occur: set the CURLOPT_VERBOSE | ||||||
|  |  option to TRUE. It'll cause the library to spew out the entire protocol | ||||||
|  |  details it sends, some internal info and some received protcol data as well | ||||||
|  |  (especially when using FTP). If you're using HTTP, adding the headers in the | ||||||
|  |  received output to study is also a clever way to get a better understanding | ||||||
|  |  wht the server behaves the way it does. Include headers in the normal body | ||||||
|  |  output with CURLOPT_HEADER set TRUE. | ||||||
|  |  | ||||||
|  |  Of course there are bugs left. We need to get to know about them to be able | ||||||
|  |  to fix them, so we're quite dependent on your bug reports! When you do report | ||||||
|  |  suspected bugs in libcurl, please include as much details you possibly can: a | ||||||
|  |  protocol dump that CURLOPT_VERBOSE produces, library version, as much as | ||||||
|  |  possible of your code that uses libcurl, operating system name and version, | ||||||
|  |  compiler name and version etc. | ||||||
|  |  | ||||||
|  |  Getting some in-depth knowledge about the protocols involved is never wrong, | ||||||
|  |  and if you're trying to do funny things, you might very well understand | ||||||
|  |  libcurl and how to use it better if you study the appropriate RFC documents | ||||||
|  |  at least briefly. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Upload Data to a Remote Site | ||||||
|  |  | ||||||
|  |  libcurl tries to keep a protocol independent approach to most transfers, thus | ||||||
|  |  uploading to a remote FTP site is very similar to uploading data to a HTTP | ||||||
|  |  server with a PUT request. | ||||||
|  |  | ||||||
|  |  Of course, first you either create an easy handle or you re-use one existing | ||||||
|  |  one. Then you set the URL to operate on just like before. This is the remote | ||||||
|  |  URL, that we now will upload. | ||||||
|  |  | ||||||
|  |  Since we write an application, we most likely want libcurl to get the upload | ||||||
|  |  data by asking us for it. To make it do that, we set the read callback and | ||||||
|  |  the custom pointer libcurl will pass to our read callback. The read callback | ||||||
|  |  should have a prototype similar to: | ||||||
|  |  | ||||||
|  |     size_t function(char *bufptr, size_t size, size_t nitems, void *userp); | ||||||
|  |  | ||||||
|  |  Where bufptr is the pointer to a buffer we fill in with data to upload and | ||||||
|  |  size*nitems is the size of the buffer and therefore also the maximum amount | ||||||
|  |  of data we can return to libcurl in this call. The 'userp' pointer is the | ||||||
|  |  custom pointer we set to point to a struct of ours to pass private data | ||||||
|  |  between the application and the callback. | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_function); | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_INFILE, &filedata); | ||||||
|  |  | ||||||
|  |  Tell libcurl that we want to upload: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, TRUE); | ||||||
|  |  | ||||||
|  |  A few protocols won't behave properly when uploads are done without any prior | ||||||
|  |  knowledge of the expected file size. HTTP PUT is one example [1]. So, set the | ||||||
|  |  upload file size using the CURLOPT_INFILESIZE like this: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE, file_size); | ||||||
|  |  | ||||||
|  |  When you call curl_easy_perform() this time, it'll perform all the necessary | ||||||
|  |  operations and when it has invoked the upload it'll call your supplied | ||||||
|  |  callback to get the data to upload. The program should return as much data as | ||||||
|  |  possible in every invoke, as that is likely to make the upload perform as | ||||||
|  |  fast as possible. The callback should return the number of bytes it wrote in | ||||||
|  |  the buffer. Returning 0 will signal the end of the upload. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Passwords | ||||||
|  |  | ||||||
|  |  Many protocols use or even require that user name and password are provided | ||||||
|  |  to be able to download or upload the data of your choice. libcurl offers | ||||||
|  |  several ways to specify them. | ||||||
|  |  | ||||||
|  |  Most protocols support that you specify the name and password in the URL | ||||||
|  |  itself. libcurl will detect this and use them accordingly. This is written | ||||||
|  |  like this: | ||||||
|  |  | ||||||
|  |         protocol://user:password@example.com/path/ | ||||||
|  |  | ||||||
|  |  If you need any odd letters in your user name or password, you should enter | ||||||
|  |  them URL encoded, as %XX where XX is a two-digit hexadecimal number. | ||||||
|  |  | ||||||
|  |  libcurl also provides options to set various passwords. The user name and | ||||||
|  |  password as shown embedded in the URL can instead get set with the | ||||||
|  |  CURLOPT_USERPWD option. The argument passed to libcurl should be a char * to | ||||||
|  |  a string in the format "user:password:". In a manner like this: | ||||||
|  |  | ||||||
|  |         curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret"); | ||||||
|  |  | ||||||
|  |  Another case where name and password might be needed at times, is for those | ||||||
|  |  users who need to athenticate themselves to a proxy they use. libcurl offers | ||||||
|  |  another option for this, the CURLOPT_PROXYUSERPWD. It is used quite similar | ||||||
|  |  to the CURLOPT_USERPWD option like this: | ||||||
|  |  | ||||||
|  |         curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "myname:thesecret"); | ||||||
|  |   | ||||||
|  |  There's a long time unix "standard" way of storing ftp user names and | ||||||
|  |  passwords, namely in the $HOME/.netrc file. The file should be made private | ||||||
|  |  so that only the user may read it (see also the "Security Considerations" | ||||||
|  |  chapter), as it might contain the password in plain text. libcurl has the | ||||||
|  |  ability to use this file to figure out what set of user name and password to | ||||||
|  |  use for a particular host. As an extension to the normal functionality, | ||||||
|  |  libcurl also supports this file for non-FTP protocols such as HTTP. To make | ||||||
|  |  curl use this file, use the CURLOPT_NETRC option: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_NETRC, TRUE); | ||||||
|  |  | ||||||
|  |  And a very basic example of how such a .netrc file may look like: | ||||||
|  |  | ||||||
|  |     machine myhost.mydomain.com | ||||||
|  |     login userlogin | ||||||
|  |     password secretword | ||||||
|  |  | ||||||
|  |  All these examples have been cases where the password has been optional, or | ||||||
|  |  at least you could leave it out and have libcurl attempt to do its job | ||||||
|  |  without it. There are times when the password isn't optional, like when | ||||||
|  |  you're using an SSL private key for secure transfers. | ||||||
|  |  | ||||||
|  |  You can in this situation either pass a password to libcurl to use to unlock | ||||||
|  |  the private key, or you can let libcurl prompt the user for it. If you prefer | ||||||
|  |  to ask the user, then you can provide your own callback function that will be | ||||||
|  |  called when libcurl wants the password. That way, you can control how the | ||||||
|  |  question will appear to the user. | ||||||
|  |  | ||||||
|  |  To pass the known private key password to libcurl: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_SSLKEYPASSWD, "keypassword"); | ||||||
|  |  | ||||||
|  |  To make a password callback: | ||||||
|  |  | ||||||
|  |     int enter_passwd(void *ourp, const char *prompt, char *buffer, int len); | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_PASSWDFUNCTION, enter_passwd); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | HTTP POSTing | ||||||
|  |  | ||||||
|  |  We get many questions regarding how to issue HTTP POSTs with libcurl the | ||||||
|  |  proper way. This chapter will thus include examples using both different | ||||||
|  |  versions of HTTP POST that libcurl supports. | ||||||
|  |  | ||||||
|  |  The first version is the simple POST, the most common version, that most HTML | ||||||
|  |  pages using the <form> tag uses. We provide a pointer to the data and tell | ||||||
|  |  libcurl to post it all to the remote site: | ||||||
|  |  | ||||||
|  |     char *data="name=daniel&project=curl"; | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, data); | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/"); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* post away! */ | ||||||
|  |  | ||||||
|  |  Simple enough, huh? Since you set the POST options with the | ||||||
|  |  CURLOPT_POSTFIELDS, this automaticly switches the handle to use POST in the | ||||||
|  |  upcoming request. | ||||||
|  |  | ||||||
|  |  Ok, so what if you want to post binary data that also requires you to set the | ||||||
|  |  Content-Type: header of the post? Well, binary posts prevents libcurl from | ||||||
|  |  being able to do strlen() on the data to figure out the size, so therefore we | ||||||
|  |  must tell libcurl the size of the post data. Setting headers in libcurl | ||||||
|  |  requests are done in a generic way, by building a list of our own headers and | ||||||
|  |  then passing that list to libcurl. | ||||||
|  |  | ||||||
|  |     struct curl_slist *headers=NULL; | ||||||
|  |     headers = curl_slist_append(headers, "Content-Type: text/xml"); | ||||||
|  |  | ||||||
|  |     /* post binary data */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_POSTFIELD, binaryptr); | ||||||
|  |  | ||||||
|  |     /* set the size of the postfields data */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDSIZE, 23); | ||||||
|  |  | ||||||
|  |     /* pass our list of custom made headers */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* post away! */ | ||||||
|  |  | ||||||
|  |     curl_slist_free_all(headers); /* free the header list */ | ||||||
|  |  | ||||||
|  |  While the simple examples above cover the majority of all cases where HTTP | ||||||
|  |  POST operations are required, they don't do multipart formposts. Multipart | ||||||
|  |  formposts were introduced as a better way to post (possibly large) binary | ||||||
|  |  data and was first documented in the RFC1867. They're called multipart | ||||||
|  |  because they're built by a chain of parts, each being a single unit. Each | ||||||
|  |  part has its own name and contents. You can in fact create and post a | ||||||
|  |  multipart formpost with the regular libcurl POST support described above, but | ||||||
|  |  that would require that you build a formpost yourself and provide to | ||||||
|  |  libcurl. To make that easier, libcurl provides curl_formadd(). Using this | ||||||
|  |  function, you add parts to the form. When you're done adding parts, you post | ||||||
|  |  the whole form. | ||||||
|  |  | ||||||
|  |  The following example sets two simple text parts with plain textual contents, | ||||||
|  |  and then a file with binary contents and upload the whole thing. | ||||||
|  |  | ||||||
|  |     struct HttpPost *post=NULL; | ||||||
|  |     struct HttpPost *last=NULL; | ||||||
|  |     curl_formadd(&post, &last, | ||||||
|  |                  CURLFORM_COPYNAME, "name", | ||||||
|  |                  CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END); | ||||||
|  |     curl_formadd(&post, &last, | ||||||
|  |                  CURLFORM_COPYNAME, "project", | ||||||
|  |                  CURLFORM_COPYCONTENTS, "curl", CURLFORM_END); | ||||||
|  |     curl_formadd(&post, &last, | ||||||
|  |                  CURLFORM_COPYNAME, "logotype-image", | ||||||
|  |                  CURLFORM_FILECONTENT, "curl.png", CURLFORM_END); | ||||||
|  |  | ||||||
|  |     /* Set the form info */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_HTTPPOST, post); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* post away! */ | ||||||
|  |  | ||||||
|  |     /* free the post data again */ | ||||||
|  |     curl_formfree(post); | ||||||
|  |  | ||||||
|  |  Multipart formposts are chains of parts using MIME-style separators and | ||||||
|  |  headers. It means that each one of these separate parts get a few headers set | ||||||
|  |  that describe the individual content-type, size etc. To enable your | ||||||
|  |  application to handicraft this formpost even more, libcurl allows you to | ||||||
|  |  supply your own set of custom headers to such an individual form part. You | ||||||
|  |  can of course supply headers to as many parts you like, but this little | ||||||
|  |  example will show how you set headers to one specific part when you add that | ||||||
|  |  to the post handle: | ||||||
|  |  | ||||||
|  |     struct curl_slist *headers=NULL; | ||||||
|  |     headers = curl_slist_append(headers, "Content-Type: text/xml"); | ||||||
|  |  | ||||||
|  |     curl_formadd(&post, &last, | ||||||
|  |                  CURLFORM_COPYNAME, "logotype-image", | ||||||
|  |                  CURLFORM_FILECONTENT, "curl.xml", | ||||||
|  |                  CURLFORM_CONTENTHEADER, headers, | ||||||
|  |                  CURLFORM_END); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* post away! */ | ||||||
|  |  | ||||||
|  |     curl_formfree(post); /* free post */ | ||||||
|  |     curl_slist_free_all(post); /* free custom header list */ | ||||||
|  |  | ||||||
|  |  Since all options on an easyhandle are "sticky", they remain the same until | ||||||
|  |  changed even if you do call curl_easy_perform(), you may need to tell curl to | ||||||
|  |  go back to a plain GET request if you intend to do such a one as your next | ||||||
|  |  request. You force an easyhandle to back to GET by using the CURLOPT_HTTPGET | ||||||
|  |  option: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_HTTPGET, TRUE); | ||||||
|  |  | ||||||
|  |  Just setting CURLOPT_POSTFIELDS to "" or NULL will *not* stop libcurl from | ||||||
|  |  doing a POST. It will just make it POST without any data to send! | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Showing Progress | ||||||
|  |  | ||||||
|  |  [ built-in progress meter, progress callback ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | libcurl with C++ | ||||||
|  |  | ||||||
|  |  There's basicly only one thing to keep in mind when using C++ instead of C | ||||||
|  |  when interfacing libcurl: | ||||||
|  |  | ||||||
|  |     "The Callbacks Must Be Plain C" | ||||||
|  |  | ||||||
|  |  So if you want a write callback set in libcurl, you should put it within | ||||||
|  |  'extern'. Similar to this: | ||||||
|  |  | ||||||
|  |      extern "C" { | ||||||
|  |        size_t write_data(void *ptr, size_t size, size_t nmemb, | ||||||
|  |                          void *ourpointer) | ||||||
|  |        { | ||||||
|  |          /* do what you want with the data */ | ||||||
|  |        } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  This will of course effectively turn the callback code into C. There won't be | ||||||
|  |  any "this" pointer available etc. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Proxies | ||||||
|  |  | ||||||
|  |  What "proxy" means according to Merriam-Webster: "a person authorized to act | ||||||
|  |  for another" but also "the agency, function, or office of a deputy who acts | ||||||
|  |  as a substitute for another". | ||||||
|  |  | ||||||
|  |  Proxies are exceedingly common these days. Companies often only offer | ||||||
|  |  internet access to employees through their HTTP proxies. Network clients or | ||||||
|  |  user-agents ask the proxy for docuements, the proxy does the actual request | ||||||
|  |  and then it returns them. | ||||||
|  |  | ||||||
|  |  libcurl has full support for HTTP proxies, so when a given URL is wanted, | ||||||
|  |  libcurl will ask the proxy for it instead of trying to connect to the actual | ||||||
|  |  host identified in the URL. | ||||||
|  |  | ||||||
|  |  The fact that the proxy is a HTTP proxy puts certain restrictions on what can | ||||||
|  |  actually happen. A requested URL that might not be a HTTP URL will be still | ||||||
|  |  be passed to the HTTP proxy to deliver back to libcurl. This happens | ||||||
|  |  transparantly, and an application may not need to know. I say "may", because | ||||||
|  |  at times it is very important to understand that all operations over a HTTP | ||||||
|  |  proxy is using the HTTP protocol. For example, you can't invoke your own | ||||||
|  |  custom FTP commands or even proper FTP directory listings. | ||||||
|  |  | ||||||
|  |   Proxy Options | ||||||
|  |  | ||||||
|  |     To tell libcurl to use a proxy at a given port number: | ||||||
|  |  | ||||||
|  |        curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080"); | ||||||
|  |  | ||||||
|  |     Some proxies require user authentication before allowing a request, and | ||||||
|  |     you pass that information similar to this: | ||||||
|  |  | ||||||
|  |        curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password"); | ||||||
|  |  | ||||||
|  |     If you want to, you can specify the host name only in the CURLOPT_PROXY | ||||||
|  |     option, and set the port number separately with CURLOPT_PROXYPORT. | ||||||
|  |  | ||||||
|  |   Environment Variables | ||||||
|  |  | ||||||
|  |     libcurl automaticly checks and uses a set of environment variables to know | ||||||
|  |     what proxies to use for certain protocols. The names of the variables are | ||||||
|  |     following an ancient de facto standard and are built up as | ||||||
|  |     "[protocol]_proxy" (note the lower casing). Which makes the variable | ||||||
|  |     'http_proxy' checked for a name of a proxy to use when the input URL is | ||||||
|  |     HTTP. Following the same rule, the variable named 'ftp_proxy' is checked | ||||||
|  |     for FTP URLs. Again, the proxies are always HTTP proxies, the different | ||||||
|  |     names of the variables simply allows different HTTP proxies to be used. | ||||||
|  |  | ||||||
|  |     The proxy environment variable contents should be in the format | ||||||
|  |     "[protocol://]machine[:port]". Where the protocol:// part is simply | ||||||
|  |     ignored if present (so http://proxy and bluerk://proxy will do the same) | ||||||
|  |     and the optional port number specifies on which port the proxy operates on | ||||||
|  |     the host. If not specified, the internal default port number will be used | ||||||
|  |     and that is most likely *not* the one you would like it to be. | ||||||
|  |  | ||||||
|  |     There are two special environment variables. 'all_proxy' is what sets | ||||||
|  |     proxy for any URL in case the protocol specific variable wasn't set, and | ||||||
|  |     'no_proxy' defines a list of hosts that should not use a proxy even though | ||||||
|  |     a variable may say so. If 'no_proxy' is a plain asterisk ("*") it matches | ||||||
|  |     all hosts. | ||||||
|  |  | ||||||
|  |   SSL and Proxies | ||||||
|  |  | ||||||
|  |     SSL is for secure point-to-point connections. This involves strong | ||||||
|  |     encryption and similar things, which effectivly makes it impossible for a | ||||||
|  |     proxy to operate as a "man in between" which the proxy's task is, as | ||||||
|  |     previously discussed. Instead, the only way to have SSL work over a HTTP | ||||||
|  |     proxy is to ask the proxy to tunnel trough everything without being able | ||||||
|  |     to check or fiddle with the traffic. | ||||||
|  |  | ||||||
|  |     Opening an SSL connection over a HTTP proxy is therefor a matter of asking | ||||||
|  |     the proxy for a straight connection to the target host on a specified | ||||||
|  |     port. This is made with the HTTP request CONNECT. ("please mr proxy, | ||||||
|  |     connect me to that remote host"). | ||||||
|  |  | ||||||
|  |     Because of the nature of this operation, where the proxy has no idea what | ||||||
|  |     kind of data that is passed in and out through this tunnel, this breaks | ||||||
|  |     some of the very few advantages that come from using a proxy, such as | ||||||
|  |     caching.  Many organizations prevent this kind of tunneling to other | ||||||
|  |     destination port numbers than 443 (which is the default HTTPS port | ||||||
|  |     number). | ||||||
|  |  | ||||||
|  |   Tunneling Through Proxy | ||||||
|  |  | ||||||
|  |     As explained above, tunneling is required for SSL to work and often even | ||||||
|  |     restricted to the operation intended for SSL; HTTPS. | ||||||
|  |  | ||||||
|  |     This is however not the only time proxy-tunneling might offer benefits to | ||||||
|  |     you or your application. | ||||||
|  |  | ||||||
|  |     As tunneling opens a direct connection from your application to the remote | ||||||
|  |     machine, it suddenly also re-introduces the ability to do non-HTTP | ||||||
|  |     operations over a HTTP proxy. You can in fact use things such as FTP | ||||||
|  |     upload or FTP custom commands this way. | ||||||
|  |  | ||||||
|  |     Again, this is often prevented by the adminstrators of proxies and is | ||||||
|  |     rarely allowed. | ||||||
|  |  | ||||||
|  |     Tell libcurl to use proxy tunneling like this: | ||||||
|  |  | ||||||
|  |        curl_easy_setopt(easyhandle, CURLOPT_HTTPPROXYTUNNEL, TRUE); | ||||||
|  |  | ||||||
|  |     In fact, there might even be times when you want to do plain HTTP | ||||||
|  |     operations using a tunnel like this, as it then enables you to operate on | ||||||
|  |     the remote server instead of asking the proxy to do so. libcurl will not | ||||||
|  |     stand in the way for such innovative actions either! | ||||||
|  |  | ||||||
|  |   Proxy Auto-Config | ||||||
|  |  | ||||||
|  |     Netscape first came up with this. It is basicly a web page (usually using | ||||||
|  |     a .pac extension) with a javascript that when executed by the browser with | ||||||
|  |     the requested URL as input, returns information to the browser on how to | ||||||
|  |     connect to the URL. The returned information might be "DIRECT" (which | ||||||
|  |     means no proxy should be used), "PROXY host:port" (to tell the browser | ||||||
|  |     where the proxy for this particular URL is) or "SOCKS host:port" (to | ||||||
|  |     direct the brower to a SOCKS proxy). | ||||||
|  |  | ||||||
|  |     libcurl has no means to interpret or evaluate javascript and thus it | ||||||
|  |     doesn't support this. If you get yourself in a position where you face | ||||||
|  |     this nasty invention, the following advice have been mentioned and used in | ||||||
|  |     the past: | ||||||
|  |  | ||||||
|  |     - Depending on the javascript complexity, write up a script that | ||||||
|  |       translates it to another language and execute that. | ||||||
|  |  | ||||||
|  |     - Read the javascript code and rewrite the same logic in another language. | ||||||
|  |  | ||||||
|  |     - Implement a javascript interpreted, people have successfully used the | ||||||
|  |       Mozilla javascript engine in the past. | ||||||
|  |  | ||||||
|  |     - Ask your admins to stop this, for a static proxy setup or similar. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Persistancy Is The Way to Happiness | ||||||
|  |  | ||||||
|  |  Re-cycling the same easy handle several times when doing multiple requests is | ||||||
|  |  the way to go. | ||||||
|  |  | ||||||
|  |  After each single curl_easy_perform() operation, libcurl will keep the | ||||||
|  |  connection alive and open. A subsequent request using the same easy handle to | ||||||
|  |  the same host might just be able to use the already open connection! This | ||||||
|  |  reduces network impact a lot. | ||||||
|  |  | ||||||
|  |  Even if the connection is dropped, all connections involving SSL to the same | ||||||
|  |  host again, will benefit from libcurl's session ID cache that drasticly | ||||||
|  |  reduces re-connection time. | ||||||
|  |  | ||||||
|  |  FTP connections that are kept alive saves a lot of time, as the command- | ||||||
|  |  response roundtrips are skipped, and also you don't risk getting blocked | ||||||
|  |  without permission to login again like on many FTP servers only allowing N | ||||||
|  |  persons to be logged in at the same time. | ||||||
|  |  | ||||||
|  |  libcurl caches DNS name resolving results, to make lookups of a previously | ||||||
|  |  looked up name a lot faster. | ||||||
|  |  | ||||||
|  |  Other interesting details that improve performance for subsequent requests | ||||||
|  |  may also be added in the future. | ||||||
|  |  | ||||||
|  |  Each easy handle will attempt to keep the last few connections alive for a | ||||||
|  |  while in case they are to be used again. You can set the size of this "cache" | ||||||
|  |  with the CURLOPT_MAXCONNECTS option. Default is 5. It is very seldom any | ||||||
|  |  point in changing this value, and if you think of changing this it is often | ||||||
|  |  just a matter of thinking again. | ||||||
|  |  | ||||||
|  |  When the connection cache gets filled, libcurl must close an existing | ||||||
|  |  connection in order to get room for the new one. To know which connection to | ||||||
|  |  close, libcurl uses a "close policy" that you can affect with the | ||||||
|  |  CURLOPT_CLOSEPOLICY option. There's only two polices implemented as of this | ||||||
|  |  writing (libcurl 7.9.4) and they are: | ||||||
|  |  | ||||||
|  |   CURLCLOSEPOLICY_LEAST_RECENTLY_USED simply close the one that hasn't been | ||||||
|  |   used for the longest time. This is the default behavior. | ||||||
|  |  | ||||||
|  |   CURLCLOSEPOLICY_OLDEST closes the oldest connection, the one that was | ||||||
|  |   createst the longest time ago. | ||||||
|  |  | ||||||
|  |  There are, or at least were, plans to support a close policy that would call | ||||||
|  |  a user-specified callback to let the user be able to decide which connection | ||||||
|  |  to dump when this is necessary and therefor is the CURLOPT_CLOSEFUNCTION an | ||||||
|  |  existing option still today. Nothing ever uses this though and this will not | ||||||
|  |  be used within the forseeable future either. | ||||||
|  |  | ||||||
|  |  To force your upcoming request to not use an already existing connection (it | ||||||
|  |  will even close one first if there happens to be one alive to the same host | ||||||
|  |  you're about to operate on), you can do that by setting CURLOPT_FRESH_CONNECT | ||||||
|  |  to TRUE. In a similar spirit, you can also forbid the upcoming request to be | ||||||
|  |  "lying" around and possibly get re-used after the request by setting | ||||||
|  |  CURLOPT_FORBID_REUSE to TRUE. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Customizing Operations | ||||||
|  |  | ||||||
|  |  There is an ongoing development today where more and more protocols are built | ||||||
|  |  upon HTTP for transport. This has obvious benefits as HTTP is a tested and | ||||||
|  |  reliable protocol that is widely deployed and have excellent proxy-support. | ||||||
|  |  | ||||||
|  |  When you use one of these protocols, and even when doing other kinds of | ||||||
|  |  programming you may need to change the traditional HTTP (or FTP or...) | ||||||
|  |  manners. You may need to change words, headers or various data. | ||||||
|  |  | ||||||
|  |  libcurl is your friend here too. | ||||||
|  |  | ||||||
|  |  If just changing the actual HTTP request keyword is what you want, like when | ||||||
|  |  GET, HEAD or POST is not good enough for you, CURLOPT_CUSTOMREQUEST is there | ||||||
|  |  for you. It is very simple to use: | ||||||
|  |  | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_CUSTOMREQUEST, "MYOWNRUQUEST"); | ||||||
|  |  | ||||||
|  |  When using the custom request, you change the request keyword of the actual | ||||||
|  |  request you are performing. Thus, by default you make GET request but you can | ||||||
|  |  also make a POST operation (as described before) and then replace the POST | ||||||
|  |  keyword if you want to. You're the boss. | ||||||
|  |  | ||||||
|  |  HTTP-like protocols pass a series of headers to the server when doing the | ||||||
|  |  request, and you're free to pass any amount of extra headers that you think | ||||||
|  |  fit. Adding headers are this easy: | ||||||
|  |  | ||||||
|  |     struct curl_slist *headers; | ||||||
|  |  | ||||||
|  |     headers = curl_slist_append(headers, "Hey-server-hey: how are you?"); | ||||||
|  |     headers = curl_slist_append(headers, "X-silly-content: yes"); | ||||||
|  |  | ||||||
|  |     /* pass our list of custom made headers */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* transfer http */ | ||||||
|  |  | ||||||
|  |     curl_slist_free_all(headers); /* free the header list */ | ||||||
|  |  | ||||||
|  |  ... and if you think some of the internally generated headers, such as | ||||||
|  |  User-Agent:, Accept: or Host: don't contain the data you want them to | ||||||
|  |  contain, you can replace them by simply setting them too: | ||||||
|  |  | ||||||
|  |     headers = curl_slist_append(headers, "User-Agent: 007"); | ||||||
|  |     headers = curl_slist_append(headers, "Host: munged.host.line"); | ||||||
|  |  | ||||||
|  |  If you replace an existing header with one with no contents, you will prevent | ||||||
|  |  the header from being sent. Like if you want to completely prevent the | ||||||
|  |  "Accept:" header to be sent, you can disable it with code similar to this: | ||||||
|  |  | ||||||
|  |     headers = curl_slist_append(headers, "Accept:"); | ||||||
|  |  | ||||||
|  |  Both replacing and cancelling internal headers should be done with careful | ||||||
|  |  consideration and you should be aware that you may violate the HTTP protocol | ||||||
|  |  when doing so. | ||||||
|  |  | ||||||
|  |  Not all protocols are HTTP-like, and thus the above may not help you when you | ||||||
|  |  want to make for example your FTP transfers to behave differently. | ||||||
|  |  | ||||||
|  |  Sending custom commands to a FTP server means that you need to send the | ||||||
|  |  comands exactly as the FTP server expects them (RFC959 is a good guide here), | ||||||
|  |  and you can only use commands that work on the control-connection alone. All | ||||||
|  |  kinds of commands that requires data interchange and thus needs a | ||||||
|  |  data-connection must be left to libcurl's own judgement. Also be aware that | ||||||
|  |  libcurl will do its very best to change directory to the target directory | ||||||
|  |  before doing any transfer, so if you change directory (with CWD or similar) | ||||||
|  |  you might confuse libcurl and then it might not attempt to transfer the file | ||||||
|  |  in the correct remote directory. | ||||||
|  |  | ||||||
|  |  A little example that deletes a given file before an operation: | ||||||
|  |  | ||||||
|  |     headers = curl_slist_append(headers, "DELE file-to-remove"); | ||||||
|  |  | ||||||
|  |     /* pass the list of custom commands to the handle */ | ||||||
|  |     curl_easy_setopt(easyhandle, CURLOPT_QUOTE, headers); | ||||||
|  |  | ||||||
|  |     curl_easy_perform(easyhandle); /* transfer ftp data! */ | ||||||
|  |  | ||||||
|  |     curl_slist_free_all(headers); /* free the header list */ | ||||||
|  |  | ||||||
|  |  If you would instead want this operation (or chain of operations) to happen | ||||||
|  |  _after_ the data transfer took place the option to curl_easy_setopt() would | ||||||
|  |  instead be called CURLOPT_POSTQUOTE and used the exact same way. | ||||||
|  |  | ||||||
|  |  The custom FTP command will be issued to the server in the same order they | ||||||
|  |  are built in the list, and if a command gets an error code returned back from | ||||||
|  |  the server no more commands will be issued and libcurl will bail out with an | ||||||
|  |  error code. Note that if you use CURLOPT_QUOTE to send commands before a | ||||||
|  |  transfer, no transfer will actually take place then. | ||||||
|  |  | ||||||
|  |  [ custom FTP commands without transfer, FTP "header-only", HTTP 1.0 ] | ||||||
|  |  | ||||||
|  | Cookies Without Chocolate Chips | ||||||
|  |  | ||||||
|  |  [ set cookies, read cookies from file, cookie-jar ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Headers Equal Fun | ||||||
|  |  | ||||||
|  |  [ use the header callback for HTTP, FTP etc ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Post Transfer Information | ||||||
|  |  | ||||||
|  |  [ curl_easy_getinfo ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Security Considerations | ||||||
|  |  | ||||||
|  |  [ ps output, netrc plain text, plain text protocols / base64 ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | SSL, Certificates and Other Tricks | ||||||
|  |  | ||||||
|  |  [ seeding, passwords, keys, certificates, ENGINE, ca certs ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Future | ||||||
|  |  | ||||||
|  |  [ multi interface, sharing between handles, mutexes, pipelining ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ----- | ||||||
|  | Footnotes: | ||||||
|  |  | ||||||
|  | [1] = HTTP PUT without knowing the size prior to transfer is indeed possible, | ||||||
|  |       but libcurl does not support the chunked transfers on uploading that is | ||||||
|  |       necessary for this feature to work. We'd gratefully appreciate patches | ||||||
|  |       that bring this functionality... | ||||||
|  |  | ||||||
|  | [2] = This happens on Windows machines when libcurl is built and used as a | ||||||
|  |       DLL. However, you can still do this on Windows if you link with a static | ||||||
|  |       library. | ||||||
|  |  | ||||||
|  | [3] = The curl-config tool is generated at build-time (on unix-like systems) | ||||||
|  |       and should be installed with the 'make install' or similar instruction | ||||||
|  |       that installs the library, header files, man pages etc. | ||||||
| @@ -6,8 +6,10 @@ | |||||||
| .SH NAME | .SH NAME | ||||||
| libcurl \- client-side URL transfers | libcurl \- client-side URL transfers | ||||||
| .SH DESCRIPTION | .SH DESCRIPTION | ||||||
| This is an overview on how to use libcurl in your c/c++ programs. There are | This is an overview on how to use libcurl in your C programs. There are | ||||||
| specific man pages for each function mentioned in here. | specific man pages for each function mentioned in here. There's also the | ||||||
|  | libcurl-the-guide document for a complete tutorial to programming with | ||||||
|  | libcurl. | ||||||
|  |  | ||||||
| libcurl can also be used directly from within your Java, PHP, Perl, Ruby or | libcurl can also be used directly from within your Java, PHP, Perl, Ruby or | ||||||
| Tcl programs as well, look elsewhere for documentation on this! | Tcl programs as well, look elsewhere for documentation on this! | ||||||
| @@ -56,9 +58,6 @@ get information about a performed transfer | |||||||
| .B curl_formadd() | .B curl_formadd() | ||||||
| helps building a HTTP form POST | helps building a HTTP form POST | ||||||
| .TP | .TP | ||||||
| .B curl_formparse() |  | ||||||
| helps building a HTTP form POST (deprecated since 7.9 use curl_formadd()!) |  | ||||||
| .TP |  | ||||||
| .B curl_formfree() | .B curl_formfree() | ||||||
| free a list built with curl_formparse()/curl_formadd() | free a list built with curl_formparse()/curl_formadd() | ||||||
| .TP | .TP | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * In order to be useful for every potential user, curl and libcurl are |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  * dual-licensed under the MPL and the MIT/X-derivate licenses. |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
| @@ -30,11 +30,11 @@ | |||||||
| # include <time.h> | # include <time.h> | ||||||
| #else | #else | ||||||
| # include <sys/types.h> | # include <sys/types.h> | ||||||
| # if TIME_WITH_SYS_TIME | # ifdef TIME_WITH_SYS_TIME | ||||||
| #  include <sys/time.h> | #  include <sys/time.h> | ||||||
| #  include <time.h> | #  include <time.h> | ||||||
| # else | # else | ||||||
| #  if HAVE_SYS_TIME_H | #  ifdef HAVE_SYS_TIME_H | ||||||
| #   include <sys/time.h> | #   include <sys/time.h> | ||||||
| #  else | #  else | ||||||
| #   include <time.h> | #   include <time.h> | ||||||
| @@ -62,6 +62,7 @@ struct HttpPost { | |||||||
|   char *contents; /* pointer to allocated data contents */ |   char *contents; /* pointer to allocated data contents */ | ||||||
|   long contentslength; /* length of contents field */ |   long contentslength; /* length of contents field */ | ||||||
|   char *contenttype; /* Content-Type */ |   char *contenttype; /* Content-Type */ | ||||||
|  |   struct curl_slist* contentheader; /* list of extra headers for this form */ | ||||||
|   struct HttpPost *more; /* if one field name has more than one file, this |   struct HttpPost *more; /* if one field name has more than one file, this | ||||||
| 			    link should link to following files */ | 			    link should link to following files */ | ||||||
|   long flags;     /* as defined below */ |   long flags;     /* as defined below */ | ||||||
| @@ -155,6 +156,8 @@ typedef enum { | |||||||
|   CURLE_OBSOLETE,	         /* 50 - removed after 7.7.3 */ |   CURLE_OBSOLETE,	         /* 50 - removed after 7.7.3 */ | ||||||
|   CURLE_SSL_PEER_CERTIFICATE,    /* 51 - peer's certificate wasn't ok */ |   CURLE_SSL_PEER_CERTIFICATE,    /* 51 - peer's certificate wasn't ok */ | ||||||
|   CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */ |   CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */ | ||||||
|  |   CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */ | ||||||
|  |   CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as default */ | ||||||
|  |  | ||||||
|   CURL_LAST /* never use! */ |   CURL_LAST /* never use! */ | ||||||
| } CURLcode; | } CURLcode; | ||||||
| @@ -212,10 +215,8 @@ typedef enum { | |||||||
|      in the CURLOPT_FLAGS to activate this */ |      in the CURLOPT_FLAGS to activate this */ | ||||||
|   CINIT(RANGE, OBJECTPOINT, 7), |   CINIT(RANGE, OBJECTPOINT, 7), | ||||||
|  |  | ||||||
| #if 0 |   /* not used */ | ||||||
|   /* Configuration flags */ |  | ||||||
|   CINIT(FLAGS, LONG, 8), |  | ||||||
| #endif |  | ||||||
|   /* Specified file stream to upload from (use as input): */ |   /* Specified file stream to upload from (use as input): */ | ||||||
|   CINIT(INFILE, OBJECTPOINT, 9), |   CINIT(INFILE, OBJECTPOINT, 9), | ||||||
|  |  | ||||||
| @@ -271,7 +272,7 @@ typedef enum { | |||||||
|   /* Set cookie in request: */ |   /* Set cookie in request: */ | ||||||
|   CINIT(COOKIE, OBJECTPOINT, 22), |   CINIT(COOKIE, OBJECTPOINT, 22), | ||||||
|  |  | ||||||
|   /* This points to a linked list of headers, struct HttpHeader kind */ |   /* This points to a linked list of headers, struct curl_slist kind */ | ||||||
|   CINIT(HTTPHEADER, OBJECTPOINT, 23), |   CINIT(HTTPHEADER, OBJECTPOINT, 23), | ||||||
|  |  | ||||||
|   /* This points to a linked list of post entries, struct HttpPost */ |   /* This points to a linked list of post entries, struct HttpPost */ | ||||||
| @@ -280,8 +281,10 @@ typedef enum { | |||||||
|   /* name of the file keeping your private SSL-certificate */ |   /* name of the file keeping your private SSL-certificate */ | ||||||
|   CINIT(SSLCERT, OBJECTPOINT, 25), |   CINIT(SSLCERT, OBJECTPOINT, 25), | ||||||
|  |  | ||||||
|   /* password for the SSL-certificate */ |   /* password for the SSL-private key, keep this for compatibility */ | ||||||
|   CINIT(SSLCERTPASSWD, OBJECTPOINT, 26), |   CINIT(SSLCERTPASSWD, OBJECTPOINT, 26), | ||||||
|  |   /* password for the SSL private key */ | ||||||
|  |   CINIT(SSLKEYPASSWD, OBJECTPOINT, 26), | ||||||
|    |    | ||||||
|   /* send TYPE parameter? */ |   /* send TYPE parameter? */ | ||||||
|   CINIT(CRLF, LONG, 27), |   CINIT(CRLF, LONG, 27), | ||||||
| @@ -298,7 +301,7 @@ typedef enum { | |||||||
|   CINIT(COOKIEFILE, OBJECTPOINT, 31), |   CINIT(COOKIEFILE, OBJECTPOINT, 31), | ||||||
|  |  | ||||||
|   /* What version to specifly try to use. |   /* What version to specifly try to use. | ||||||
|      3 = SSLv3, 2 = SSLv2, all else makes it try v3 first then v2 */ |      See CURL_SSLVERSION defines below. */ | ||||||
|   CINIT(SSLVERSION, LONG, 32), |   CINIT(SSLVERSION, LONG, 32), | ||||||
|  |  | ||||||
|   /* What kind of HTTP time condition to use, see defines */ |   /* What kind of HTTP time condition to use, see defines */ | ||||||
| @@ -321,11 +324,8 @@ typedef enum { | |||||||
|   /* HTTP request, for odd commands like DELETE, TRACE and others */ |   /* HTTP request, for odd commands like DELETE, TRACE and others */ | ||||||
|   CINIT(STDERR, OBJECTPOINT, 37), |   CINIT(STDERR, OBJECTPOINT, 37), | ||||||
|  |  | ||||||
| #if 0 |   /* 38 is not used */ | ||||||
|   /* Progress mode set alternative progress mode displays. Alternative |  | ||||||
|      ones should now be made by the client, not the lib! */      |  | ||||||
|   CINIT(PROGRESSMODE, LONG, 38), |  | ||||||
| #endif |  | ||||||
|   /* send linked-list of post-transfer QUOTE commands */ |   /* send linked-list of post-transfer QUOTE commands */ | ||||||
|   CINIT(POSTQUOTE, OBJECTPOINT, 39), |   CINIT(POSTQUOTE, OBJECTPOINT, 39), | ||||||
|  |  | ||||||
| @@ -466,6 +466,34 @@ typedef enum { | |||||||
|      CURL_HTTP_VERSION* enums set below. */ |      CURL_HTTP_VERSION* enums set below. */ | ||||||
|   CINIT(HTTP_VERSION, LONG, 84), |   CINIT(HTTP_VERSION, LONG, 84), | ||||||
|  |  | ||||||
|  |   /* Specificly switch on or off the FTP engine's use of the EPSV command. By | ||||||
|  |      default, that one will always be attempted before the more traditional | ||||||
|  |      PASV command. */      | ||||||
|  |   CINIT(FTP_USE_EPSV, LONG, 85), | ||||||
|  |  | ||||||
|  |   /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ | ||||||
|  |   CINIT(SSLCERTTYPE, OBJECTPOINT, 86), | ||||||
|  |  | ||||||
|  |   /* name of the file keeping your private SSL-key */ | ||||||
|  |   CINIT(SSLKEY, OBJECTPOINT, 87), | ||||||
|  |  | ||||||
|  |   /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ | ||||||
|  |   CINIT(SSLKEYTYPE, OBJECTPOINT, 88), | ||||||
|  |  | ||||||
|  |   /* crypto engine for the SSL-sub system */ | ||||||
|  |   CINIT(SSLENGINE, OBJECTPOINT, 89), | ||||||
|  |  | ||||||
|  |   /* set the crypto engine for the SSL-sub system as default | ||||||
|  |      the param has no meaning... | ||||||
|  |    */ | ||||||
|  |   CINIT(SSLENGINE_DEFAULT, LONG, 90), | ||||||
|  |  | ||||||
|  |   /* Non-zero value means to use the global dns cache */ | ||||||
|  |   CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), | ||||||
|  |  | ||||||
|  |   /* DNS cache timeout */ | ||||||
|  |   CINIT(DNS_CACHE_TIMEOUT, LONG, 92), | ||||||
|  |    | ||||||
|   CURLOPT_LASTENTRY /* the last unusued */ |   CURLOPT_LASTENTRY /* the last unusued */ | ||||||
| } CURLoption; | } CURLoption; | ||||||
|  |  | ||||||
| @@ -480,6 +508,15 @@ enum { | |||||||
|   CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ |   CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  |   CURL_SSLVERSION_DEFAULT, | ||||||
|  |   CURL_SSLVERSION_TLSv1, | ||||||
|  |   CURL_SSLVERSION_SSLv2, | ||||||
|  |   CURL_SSLVERSION_SSLv3, | ||||||
|  |  | ||||||
|  |   CURL_SSLVERSION_LAST /* never use, keep last */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|   TIMECOND_NONE, |   TIMECOND_NONE, | ||||||
| @@ -534,6 +571,7 @@ typedef enum { | |||||||
|   CFINIT(ARRAY_START), /* below are the options allowed within a array */ |   CFINIT(ARRAY_START), /* below are the options allowed within a array */ | ||||||
|   CFINIT(FILE), |   CFINIT(FILE), | ||||||
|   CFINIT(CONTENTTYPE), |   CFINIT(CONTENTTYPE), | ||||||
|  |   CFINIT(CONTENTHEADER), | ||||||
|   CFINIT(END), |   CFINIT(END), | ||||||
|   CFINIT(ARRAY_END),   /* up are the options allowed within a array */ |   CFINIT(ARRAY_END),   /* up are the options allowed within a array */ | ||||||
|  |  | ||||||
| @@ -575,8 +613,8 @@ CURLcode curl_global_init(long flags); | |||||||
| void curl_global_cleanup(void); | void curl_global_cleanup(void); | ||||||
|  |  | ||||||
| /* This is the version number */ | /* This is the version number */ | ||||||
| #define LIBCURL_VERSION "7.9.1" | #define LIBCURL_VERSION "7.9.4" | ||||||
| #define LIBCURL_VERSION_NUM 0x070901 | #define LIBCURL_VERSION_NUM 0x070904 | ||||||
|  |  | ||||||
| /* linked-list structure for the CURLOPT_QUOTE option (and other) */ | /* linked-list structure for the CURLOPT_QUOTE option (and other) */ | ||||||
| struct curl_slist { | struct curl_slist { | ||||||
| @@ -626,7 +664,13 @@ typedef enum { | |||||||
|   CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15, |   CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15, | ||||||
|   CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16, |   CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16, | ||||||
|  |  | ||||||
|   CURLINFO_LASTONE          = 17 |   CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, | ||||||
|  |  | ||||||
|  |   CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, | ||||||
|  |  | ||||||
|  |   /* Fill in new entries here! */ | ||||||
|  |  | ||||||
|  |   CURLINFO_LASTONE          = 19 | ||||||
| } CURLINFO; | } CURLINFO; | ||||||
|  |  | ||||||
| /* unfortunately, the easy.h include file needs the options and info stuff | /* unfortunately, the easy.h include file needs the options and info stuff | ||||||
|   | |||||||
| @@ -6,13 +6,11 @@ AUTOMAKE_OPTIONS = foreign no-dependencies | |||||||
|  |  | ||||||
| EXTRA_DIST = getdate.y \ | EXTRA_DIST = getdate.y \ | ||||||
|        Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \ |        Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \ | ||||||
|        libcurl.def dllinit.c curllib.dsp curllib.dsw |        libcurl.def dllinit.c curllib.dsp curllib.dsw \ | ||||||
|  |        config-vms.h config-win32.h config-riscos.h config-mac.h | ||||||
|  |  | ||||||
| lib_LTLIBRARIES = libcurl.la | lib_LTLIBRARIES = libcurl.la | ||||||
|  |  | ||||||
| # Some flags needed when trying to cause warnings ;-) |  | ||||||
| # CFLAGS = -DMALLOCDEBUG -g # -Wall #-pedantic |  | ||||||
|  |  | ||||||
| INCLUDES = -I$(top_srcdir)/include | INCLUDES = -I$(top_srcdir)/include | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -59,7 +57,9 @@ escape.c       mprintf.c      telnet.c       \ | |||||||
| escape.h       getpass.c      netrc.c        telnet.h       \ | escape.h       getpass.c      netrc.c        telnet.h       \ | ||||||
| getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \ | getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \ | ||||||
| security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \ | security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \ | ||||||
| http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h | http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h \ | ||||||
|  | llist.c llist.h hash.c hash.h multi.c multi.h | ||||||
|  |  | ||||||
|  |  | ||||||
| noinst_HEADERS = setup.h transfer.h | noinst_HEADERS = setup.h transfer.h | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ INCDIRS    = -I$(CURNTDIR);$(TOPDIR)/include/ | |||||||
| # 'BCCDIR' has to be set up in your c:\autoexec.bat | # 'BCCDIR' has to be set up in your c:\autoexec.bat | ||||||
| # i.e. SET BCCDIR = c:\Borland\BCC55 | # i.e. SET BCCDIR = c:\Borland\BCC55 | ||||||
| # where c:\Borland\BCC55 is the compiler is installed | # where c:\Borland\BCC55 is the compiler is installed | ||||||
| LINKLIB	   = $(BCCDIR)/lib/psdk/wsock32.lib | LINKLIB	   = $(BCCDIR)/lib/psdk/ws2_32.lib | ||||||
| LIBCURLLIB = libcurl.lib | LIBCURLLIB = libcurl.lib | ||||||
|  |  | ||||||
| .SUFFIXES: .c | .SUFFIXES: .c | ||||||
|   | |||||||
| @@ -27,5 +27,5 @@ | |||||||
| +version.obj & | +version.obj & | ||||||
| +easy.obj & | +easy.obj & | ||||||
| +strequal.obj & | +strequal.obj & | ||||||
| +strtok.obj | +strtok.obj & | ||||||
|  | +connect.obj | ||||||
|   | |||||||
| @@ -35,14 +35,14 @@ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \ | |||||||
| 	ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c	\ | 	ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c	\ | ||||||
| 	telnet.h getinfo.c strequal.c strequal.h easy.c security.h		\ | 	telnet.h getinfo.c strequal.c strequal.h easy.c security.h		\ | ||||||
| 	security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \ | 	security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \ | ||||||
| 	strtok.c connect.c | 	strtok.c connect.c hash.c llist.c | ||||||
|  |  | ||||||
| libcurl_a_OBJECTS =  file.o timeval.o base64.o hostip.o progress.o \ | libcurl_a_OBJECTS =  file.o timeval.o base64.o hostip.o progress.o \ | ||||||
| 	formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \ | 	formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \ | ||||||
| 	speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \ | 	speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \ | ||||||
| 	getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \ | 	getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \ | ||||||
| 	strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \ | 	strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \ | ||||||
| 	strtok.o connect.o | 	strtok.o connect.o hash.o llist.o | ||||||
|  |  | ||||||
| LIBRARIES =  $(libcurl_a_LIBRARIES) | LIBRARIES =  $(libcurl_a_LIBRARIES) | ||||||
| SOURCES = $(libcurl_a_SOURCES) | SOURCES = $(libcurl_a_SOURCES) | ||||||
|   | |||||||
							
								
								
									
										555
									
								
								lib/Makefile.vc6
									
									
									
									
									
								
							
							
						
						
									
										555
									
								
								lib/Makefile.vc6
									
									
									
									
									
								
							| @@ -1,377 +1,226 @@ | |||||||
| ############################################################# | ############################################################# | ||||||
| # | # | ||||||
| ## Makefile for building libcurl.lib with MSVC6 | # Makefile for building libcurl with MSVC6 | ||||||
| ## Use: nmake -f makefile.vc6 [release | release-ssl | debug] | # | ||||||
| ##      (default is release) | # Usage: see usage message below | ||||||
| ## | #        Should be invoked from \lib directory | ||||||
| ## Originally written by: Troy Engel <tengel@sonic.net> | #        Edit the paths and desired library name | ||||||
| ## Updated by: Craig Davison <cd@securityfocus.com> | #        SSL path is only required if you intend compiling | ||||||
| ## Updated by: SM <sm@technologist.com> | #        with SSL. | ||||||
|  | # | ||||||
|  | # This make file leaves the result either a .lib or .dll file | ||||||
|  | # in the \lib directory. It should be called from the \lib | ||||||
|  | # directory. | ||||||
|  | # | ||||||
|  | # An option would have been to allow the source directory to | ||||||
|  | # be specified, but I saw no requirement. | ||||||
|  | # | ||||||
|  | # Another option would have been to leave the .lib and .dll | ||||||
|  | # files in the "cfg" directory, but then the make file | ||||||
|  | # in \src would need to be changed. | ||||||
|  | # | ||||||
|  | ############################################################## | ||||||
|  | # CHANGE LOG | ||||||
|  | # ------------------------------------------------------------ | ||||||
|  | # 05.11.2001   John Lask   Initial Release | ||||||
|  | # 02.05.2002   Miklos Nemeth OPENSSL_PATH environment; no need | ||||||
|  | #              for OpenSSL libraries when creating a  | ||||||
|  | #              static libcurl.lib | ||||||
|  | # | ||||||
|  | # | ||||||
|  | ############################################################## | ||||||
|  |  | ||||||
| PROGRAM_NAME = libcurl.lib | LIB_NAME       = libcurl | ||||||
| PROGRAM_NAME_DEBUG = libcurld.lib | LIB_NAME_DEBUG = libcurld | ||||||
| #OPENSSL_PATH = ../../openssl-0.9.6b | !IFNDEF OPENSSL_PATH | ||||||
|  | OPENSSL_PATH   = ../../openssl-0.9.6 | ||||||
|  | !ENDIF | ||||||
|  |  | ||||||
| ######################################################## | ############################################################# | ||||||
| ## Nothing more to do below this line! | ## Nothing more to do below this line! | ||||||
|  |  | ||||||
| ## Release | CCNODBG   = cl.exe /MD /O2 /D "NDEBUG" | ||||||
| CCR = cl.exe /MD /O2 /D "NDEBUG" | CCDEBUG   = cl.exe /MDd /Od /Gm /Zi  /D "_DEBUG" /GZ | ||||||
| LINKR = link.exe -lib /out:$(PROGRAM_NAME) | CFLAGSSSL = /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" | ||||||
|  |  | ||||||
| ## Debug |  | ||||||
| CCD = cl.exe /MDd /Gm /ZI /Od /D "_DEBUG" /GZ |  | ||||||
| LINKD = link.exe -lib /out:$(PROGRAM_NAME_DEBUG) |  | ||||||
|  |  | ||||||
| ## SSL Release |  | ||||||
| CCRS = cl.exe /MD /O2 /D "NDEBUG" /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" |  | ||||||
| LINKRS = link.exe -lib /out:$(PROGRAM_NAME) /LIBPATH:$(OPENSSL_PATH)/out32dll |  | ||||||
|  |  | ||||||
| CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS" | CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS" | ||||||
|  |  | ||||||
|  | LNKDLL    = link.exe /DLL  /def:libcurl.def | ||||||
|  | LNKLIB    = link.exe -lib | ||||||
| LFLAGS    = /nologo | LFLAGS    = /nologo | ||||||
|  | LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)/out32dll | ||||||
| LINKLIBS  = ws2_32.lib | LINKLIBS  = ws2_32.lib | ||||||
| LINKSLIBS = libeay32.lib ssleay32.lib RSAglue.lib | SSLLIBS   = libeay32.lib ssleay32.lib RSAglue.lib | ||||||
|  | CFGSET    = FALSE | ||||||
|  | LFLAGSSSL= | ||||||
|  | SSLLIBS  = | ||||||
|  |  | ||||||
| RELEASE_OBJS= \ | ###################### | ||||||
| 	base64r.obj \ | # release | ||||||
| 	cookier.obj \ |  | ||||||
| 	transferr.obj \ |  | ||||||
| 	escaper.obj \ |  | ||||||
| 	formdatar.obj \ |  | ||||||
| 	ftpr.obj \ |  | ||||||
| 	httpr.obj \ |  | ||||||
| 	http_chunksr.obj \ |  | ||||||
| 	ldapr.obj \ |  | ||||||
| 	dictr.obj \ |  | ||||||
| 	telnetr.obj \ |  | ||||||
| 	getdater.obj \ |  | ||||||
| 	getenvr.obj \ |  | ||||||
| 	getpassr.obj \ |  | ||||||
| 	hostipr.obj \ |  | ||||||
| 	if2ipr.obj \ |  | ||||||
| 	mprintfr.obj \ |  | ||||||
| 	netrcr.obj \ |  | ||||||
| 	progressr.obj \ |  | ||||||
| 	sendfr.obj \ |  | ||||||
| 	speedcheckr.obj \ |  | ||||||
| 	ssluser.obj \ |  | ||||||
| 	timevalr.obj \ |  | ||||||
| 	urlr.obj \ |  | ||||||
| 	filer.obj \ |  | ||||||
| 	getinfor.obj \ |  | ||||||
| 	versionr.obj \ |  | ||||||
| 	easyr.obj \ |  | ||||||
| 	strequalr.obj \ |  | ||||||
| 	strtokr.obj \ |  | ||||||
| 	connectr.obj |  | ||||||
|  |  | ||||||
| DEBUG_OBJS= \ | !IF "$(CFG)" == "release" | ||||||
| 	base64d.obj \ | TARGET =$(LIB_NAME).lib | ||||||
| 	cookied.obj \ | DIROBJ =.\$(CFG) | ||||||
| 	transferd.obj \ | LNK    = $(LNKLIB) /out:$(TARGET) | ||||||
| 	escaped.obj \ | CC     = $(CCNODBG) | ||||||
| 	formdatad.obj \ | CFGSET = TRUE | ||||||
| 	ftpd.obj \ | !ENDIF | ||||||
| 	httpd.obj \ |  | ||||||
| 	http_chunksd.obj \ |  | ||||||
| 	ldapd.obj \ |  | ||||||
| 	dictd.obj \ |  | ||||||
| 	telnetd.obj \ |  | ||||||
| 	getdated.obj \ |  | ||||||
| 	getenvd.obj \ |  | ||||||
| 	getpassd.obj \ |  | ||||||
| 	hostipd.obj \ |  | ||||||
| 	if2ipd.obj \ |  | ||||||
| 	mprintfd.obj \ |  | ||||||
| 	netrcd.obj \ |  | ||||||
| 	progressd.obj \ |  | ||||||
| 	sendfd.obj \ |  | ||||||
| 	speedcheckd.obj \ |  | ||||||
| 	sslused.obj \ |  | ||||||
| 	timevald.obj \ |  | ||||||
| 	urld.obj \ |  | ||||||
| 	filed.obj \ |  | ||||||
| 	getinfod.obj \ |  | ||||||
| 	versiond.obj  \ |  | ||||||
| 	easyd.obj \ |  | ||||||
| 	strequald.obj \ |  | ||||||
| 	strtokd.obj \ |  | ||||||
| 	connectd.obj |  | ||||||
|  |  | ||||||
| RELEASE_SSL_OBJS= \ | ###################### | ||||||
| 	base64rs.obj \ | # release-dll | ||||||
| 	cookiers.obj \ |  | ||||||
| 	transferrs.obj \ |  | ||||||
| 	escapers.obj \ |  | ||||||
| 	formdatars.obj \ |  | ||||||
| 	ftprs.obj \ |  | ||||||
| 	httprs.obj \ |  | ||||||
| 	http_chunksrs.obj \ |  | ||||||
| 	ldaprs.obj \ |  | ||||||
| 	dictrs.obj \ |  | ||||||
| 	telnetrs.obj \ |  | ||||||
| 	getdaters.obj \ |  | ||||||
| 	getenvrs.obj \ |  | ||||||
| 	getpassrs.obj \ |  | ||||||
| 	hostiprs.obj \ |  | ||||||
| 	if2iprs.obj \ |  | ||||||
| 	mprintfrs.obj \ |  | ||||||
| 	netrcrs.obj \ |  | ||||||
| 	progressrs.obj \ |  | ||||||
| 	sendfrs.obj \ |  | ||||||
| 	speedcheckrs.obj \ |  | ||||||
| 	sslusers.obj \ |  | ||||||
| 	timevalrs.obj \ |  | ||||||
| 	urlrs.obj \ |  | ||||||
| 	filers.obj \ |  | ||||||
| 	getinfors.obj \ |  | ||||||
| 	versionrs.obj \ |  | ||||||
| 	easyrs.obj \ |  | ||||||
| 	strequalrs.obj \ |  | ||||||
| 	strtokrs.obj \ |  | ||||||
| 	connectrs.obj |  | ||||||
|  |  | ||||||
| LINK_OBJS= \ | !IF "$(CFG)" == "release-dll" | ||||||
| 	base64.obj \ | TARGET =$(LIB_NAME).dll | ||||||
| 	cookie.obj \ | DIROBJ =.\$(CFG) | ||||||
| 	transfer.obj \ | LNK    = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib" | ||||||
| 	escape.obj \ | CC     = $(CCNODBG) | ||||||
| 	formdata.obj \ | CFGSET = TRUE | ||||||
| 	ftp.obj \ | !ENDIF | ||||||
| 	http.obj \ |  | ||||||
| 	http_chunks.obj \ |  | ||||||
| 	ldap.obj \ |  | ||||||
| 	dict.obj \ |  | ||||||
| 	telnet.obj \ |  | ||||||
| 	getdate.obj \ |  | ||||||
| 	getenv.obj \ |  | ||||||
| 	getpass.obj \ |  | ||||||
| 	hostip.obj \ |  | ||||||
| 	if2ip.obj \ |  | ||||||
| 	mprintf.obj \ |  | ||||||
| 	netrc.obj \ |  | ||||||
| 	progress.obj \ |  | ||||||
| 	sendf.obj \ |  | ||||||
| 	speedcheck.obj \ |  | ||||||
| 	ssluse.obj \ |  | ||||||
| 	timeval.obj \ |  | ||||||
| 	url.obj \ |  | ||||||
| 	file.obj \ |  | ||||||
| 	getinfo.obj \ |  | ||||||
| 	version.obj \ |  | ||||||
| 	easy.obj \ |  | ||||||
| 	strequal.obj \ |  | ||||||
| 	strtok.obj \ |  | ||||||
| 	connect.obj |  | ||||||
|  |  | ||||||
| all : release | ###################### | ||||||
|  | # release-ssl | ||||||
|  |  | ||||||
| release: $(RELEASE_OBJS) | !IF "$(CFG)" == "release-ssl" | ||||||
| 	$(LINKR) $(LFLAGS) $(LINKLIBS) $(LINK_OBJS) | TARGET   =$(LIB_NAME).lib | ||||||
|  | DIROBJ   =.\$(CFG) | ||||||
|  | LNK      = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) | ||||||
|  | LINKLIBS = $(LINKLIBS) $(SSLLIBS) | ||||||
|  | CC       = $(CCNODBG) $(CFLAGSSSL) | ||||||
|  | CFGSET   = TRUE | ||||||
|  | !ENDIF | ||||||
|  |  | ||||||
| debug: $(DEBUG_OBJS) | ###################### | ||||||
| 	$(LINKD) $(LFLAGS) $(LINKLIBS) $(LINK_OBJS) | # release-ssl-dll | ||||||
|  |  | ||||||
| release-ssl: $(RELEASE_SSL_OBJS) | !IF "$(CFG)" == "release-ssl-dll" | ||||||
| 	$(LINKRS) $(LFLAGS) $(LINKLIBS) $(LINKSLIBS) $(LINK_OBJS) | TARGET   =$(LIB_NAME).dll | ||||||
|  | DIROBJ   =.\$(CFG) | ||||||
|  | LNK      = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib" | ||||||
|  | LINKLIBS = $(LINKLIBS) $(SSLLIBS) | ||||||
|  | CC       = $(CCNODBG)  $(CFLAGSSSL) | ||||||
|  | CFGSET   = TRUE | ||||||
|  | !ENDIF | ||||||
|  |  | ||||||
| ## Release |  | ||||||
| base64r.obj: base64.c |  | ||||||
| 	$(CCR) $(CFLAGS) base64.c |  | ||||||
| cookier.obj: cookie.c |  | ||||||
| 	$(CCR) $(CFLAGS) cookie.c |  | ||||||
| transferr.obj: transfer.c |  | ||||||
| 	$(CCR) $(CFLAGS) transfer.c |  | ||||||
| escaper.obj: escape.c |  | ||||||
| 	$(CCR) $(CFLAGS) escape.c |  | ||||||
| formdatar.obj: formdata.c |  | ||||||
| 	$(CCR) $(CFLAGS) formdata.c |  | ||||||
| ftpr.obj: ftp.c |  | ||||||
| 	$(CCR) $(CFLAGS) ftp.c |  | ||||||
| httpr.obj: http.c |  | ||||||
| 	$(CCR) $(CFLAGS) http.c |  | ||||||
| http_chunksr.obj: http_chunks.c |  | ||||||
| 	$(CCR) $(CFLAGS) http_chunks.c |  | ||||||
| ldapr.obj: ldap.c |  | ||||||
| 	$(CCR) $(CFLAGS) ldap.c |  | ||||||
| dictr.obj: dict.c |  | ||||||
| 	$(CCR) $(CFLAGS) dict.c |  | ||||||
| telnetr.obj: telnet.c |  | ||||||
| 	$(CCR) $(CFLAGS) telnet.c |  | ||||||
| getdater.obj: getdate.c |  | ||||||
| 	$(CCR) $(CFLAGS) getdate.c |  | ||||||
| getenvr.obj: getenv.c |  | ||||||
| 	$(CCR) $(CFLAGS) getenv.c |  | ||||||
| getpassr.obj: getpass.c |  | ||||||
| 	$(CCR) $(CFLAGS) getpass.c |  | ||||||
| hostipr.obj: hostip.c |  | ||||||
| 	$(CCR) $(CFLAGS) hostip.c |  | ||||||
| if2ipr.obj: if2ip.c |  | ||||||
| 	$(CCR) $(CFLAGS) if2ip.c |  | ||||||
| mprintfr.obj: mprintf.c |  | ||||||
| 	$(CCR) $(CFLAGS) mprintf.c |  | ||||||
| netrcr.obj: netrc.c |  | ||||||
| 	$(CCR) $(CFLAGS) netrc.c |  | ||||||
| progressr.obj: progress.c |  | ||||||
| 	$(CCR) $(CFLAGS) progress.c |  | ||||||
| sendfr.obj: sendf.c |  | ||||||
| 	$(CCR) $(CFLAGS) sendf.c |  | ||||||
| speedcheckr.obj: speedcheck.c |  | ||||||
| 	$(CCR) $(CFLAGS) speedcheck.c |  | ||||||
| ssluser.obj: ssluse.c |  | ||||||
| 	$(CCR) $(CFLAGS) ssluse.c |  | ||||||
| timevalr.obj: timeval.c |  | ||||||
| 	$(CCR) $(CFLAGS) timeval.c |  | ||||||
| urlr.obj: url.c |  | ||||||
| 	$(CCR) $(CFLAGS) url.c |  | ||||||
| filer.obj: file.c |  | ||||||
| 	$(CCR) $(CFLAGS) file.c |  | ||||||
| getinfor.obj: getinfo.c |  | ||||||
| 	$(CCR) $(CFLAGS) getinfo.c |  | ||||||
| versionr.obj: version.c |  | ||||||
| 	$(CCR) $(CFLAGS) version.c |  | ||||||
| easyr.obj: easy.c |  | ||||||
| 	$(CCR) $(CFLAGS) easy.c |  | ||||||
| strequalr.obj: strequal.c |  | ||||||
| 	$(CCR) $(CFLAGS) strequal.c |  | ||||||
| strtokr.obj:strtok.c |  | ||||||
| 	$(CCR) $(CFLAGS) strtok.c |  | ||||||
| connectr.obj:connect.c |  | ||||||
| 	$(CCR) $(CFLAGS) connect.c |  | ||||||
|  |  | ||||||
| ## Debug |  | ||||||
| base64d.obj: base64.c |  | ||||||
| 	$(CCD) $(CFLAGS) base64.c |  | ||||||
| cookied.obj: cookie.c |  | ||||||
| 	$(CCD) $(CFLAGS) cookie.c |  | ||||||
| transferd.obj: transfer.c |  | ||||||
| 	$(CCD) $(CFLAGS) transfer.c |  | ||||||
| escaped.obj: escape.c |  | ||||||
| 	$(CCD) $(CFLAGS) escape.c |  | ||||||
| formdatad.obj: formdata.c |  | ||||||
| 	$(CCD) $(CFLAGS) formdata.c |  | ||||||
| ftpd.obj: ftp.c |  | ||||||
| 	$(CCD) $(CFLAGS) ftp.c |  | ||||||
| httpd.obj: http.c |  | ||||||
| 	$(CCD) $(CFLAGS) http.c |  | ||||||
| http_chunksd.obj: http_chunks.c |  | ||||||
| 	$(CCD) $(CFLAGS) http_chunks.c |  | ||||||
| ldapd.obj: ldap.c |  | ||||||
| 	$(CCD) $(CFLAGS) ldap.c |  | ||||||
| dictd.obj: dict.c |  | ||||||
| 	$(CCD) $(CFLAGS) dict.c |  | ||||||
| telnetd.obj: telnet.c |  | ||||||
| 	$(CCD) $(CFLAGS) telnet.c |  | ||||||
| getdated.obj: getdate.c |  | ||||||
| 	$(CCD) $(CFLAGS) getdate.c |  | ||||||
| getenvd.obj: getenv.c |  | ||||||
| 	$(CCD) $(CFLAGS) getenv.c |  | ||||||
| getpassd.obj: getpass.c |  | ||||||
| 	$(CCD) $(CFLAGS) getpass.c |  | ||||||
| hostipd.obj: hostip.c |  | ||||||
| 	$(CCD) $(CFLAGS) hostip.c |  | ||||||
| if2ipd.obj: if2ip.c |  | ||||||
| 	$(CCD) $(CFLAGS) if2ip.c |  | ||||||
| mprintfd.obj: mprintf.c |  | ||||||
| 	$(CCD) $(CFLAGS) mprintf.c |  | ||||||
| netrcd.obj: netrc.c |  | ||||||
| 	$(CCD) $(CFLAGS) netrc.c |  | ||||||
| progressd.obj: progress.c |  | ||||||
| 	$(CCD) $(CFLAGS) progress.c |  | ||||||
| sendfd.obj: sendf.c |  | ||||||
| 	$(CCD) $(CFLAGS) sendf.c |  | ||||||
| speedcheckd.obj: speedcheck.c |  | ||||||
| 	$(CCD) $(CFLAGS) speedcheck.c |  | ||||||
| sslused.obj: ssluse.c |  | ||||||
| 	$(CCD) $(CFLAGS) ssluse.c |  | ||||||
| timevald.obj: timeval.c |  | ||||||
| 	$(CCD) $(CFLAGS) timeval.c |  | ||||||
| urld.obj: url.c |  | ||||||
| 	$(CCD) $(CFLAGS) url.c |  | ||||||
| filed.obj: file.c |  | ||||||
| 	$(CCD) $(CFLAGS) file.c |  | ||||||
| getinfod.obj: getinfo.c |  | ||||||
| 	$(CCD) $(CFLAGS) getinfo.c |  | ||||||
| versiond.obj: version.c |  | ||||||
| 	$(CCD) $(CFLAGS) version.c |  | ||||||
| easyd.obj: easy.c |  | ||||||
| 	$(CCD) $(CFLAGS) easy.c |  | ||||||
| strequald.obj: strequal.c |  | ||||||
| 	$(CCD) $(CFLAGS) strequal.c |  | ||||||
| strtokd.obj:strtok.c |  | ||||||
| 	$(CCD) $(CFLAGS) strtok.c |  | ||||||
| connectd.obj:connect.c |  | ||||||
| 	$(CCR) $(CFLAGS) connect.c |  | ||||||
|  |  | ||||||
| ## Release SSL |  | ||||||
| base64rs.obj: base64.c | ###################### | ||||||
| 	$(CCRS) $(CFLAGS) base64.c | # debug | ||||||
| cookiers.obj: cookie.c |  | ||||||
| 	$(CCRS) $(CFLAGS) cookie.c | !IF "$(CFG)" == "debug" | ||||||
| transferrs.obj: transfer.c | TARGET =$(LIB_NAME_DEBUG).lib | ||||||
| 	$(CCRS) $(CFLAGS) transfer.c | DIROBJ =.\$(CFG) | ||||||
| escapers.obj: escape.c | LNK    = $(LNKLIB) /out:$(TARGET) | ||||||
| 	$(CCRS) $(CFLAGS) escape.c | CC     = $(CCDEBUG) | ||||||
| formdatars.obj: formdata.c | CFGSET = TRUE | ||||||
| 	$(CCRS) $(CFLAGS) formdata.c | !ENDIF | ||||||
| ftprs.obj: ftp.c |  | ||||||
| 	$(CCRS) $(CFLAGS) ftp.c | ###################### | ||||||
| httprs.obj: http.c | # debug-dll | ||||||
| 	$(CCRS) $(CFLAGS) http.c |  | ||||||
| http_chunksrs.obj: http_chunks.c | !IF "$(CFG)" == "debug-dll" | ||||||
| 	$(CCRS) $(CFLAGS) http_chunks.c | TARGET =$(LIB_NAME_DEBUG).dll | ||||||
| ldaprs.obj: ldap.c | DIROBJ =.\$(CFG) | ||||||
| 	$(CCRS) $(CFLAGS) ldap.c | LNK    = $(LNKDLL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" | ||||||
| dictrs.obj: dict.c | CC     = $(CCDEBUG) | ||||||
| 	$(CCRS) $(CFLAGS) dict.c | CFGSET = TRUE | ||||||
| telnetrs.obj: telnet.c | !ENDIF | ||||||
| 	$(CCRS) $(CFLAGS) telnet.c |  | ||||||
| getdaters.obj: getdate.c | ###################### | ||||||
| 	$(CCRS) $(CFLAGS) getdate.c | # debug-ssl | ||||||
| getenvrs.obj: getenv.c | #todo | ||||||
| 	$(CCRS) $(CFLAGS) getenv.c | !IF "$(CFG)" == "debug-ssl" | ||||||
| getpassrs.obj: getpass.c | TARGET   = $(LIB_NAME_DEBUG).lib | ||||||
| 	$(CCRS) $(CFLAGS) getpass.c | DIROBJ   =.\$(CFG) | ||||||
| hostiprs.obj: hostip.c | LNK      = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET) | ||||||
| 	$(CCRS) $(CFLAGS) hostip.c | LINKLIBS = $(LINKLIBS) $(SSLLIBS) | ||||||
| if2iprs.obj: if2ip.c | CC       = $(CCDEBUG) $(CFLAGSSSL) | ||||||
| 	$(CCRS) $(CFLAGS) if2ip.c | CFGSET   = TRUE | ||||||
| mprintfrs.obj: mprintf.c | !ENDIF | ||||||
| 	$(CCRS) $(CFLAGS) mprintf.c |  | ||||||
| netrcrs.obj: netrc.c | ###################### | ||||||
| 	$(CCRS) $(CFLAGS) netrc.c | # debug-ssl-dll | ||||||
| progressrs.obj: progress.c |  | ||||||
| 	$(CCRS) $(CFLAGS) progress.c | !IF "$(CFG)" == "debug-ssl-dll" | ||||||
| sendfrs.obj: sendf.c | TARGET   =$(LIB_NAME_DEBUG).dll | ||||||
| 	$(CCRS) $(CFLAGS) sendf.c | DIROBJ   =.\$(CFG) | ||||||
| speedcheckrs.obj: speedcheck.c | LNK      = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME_DEBUG).lib" | ||||||
| 	$(CCRS) $(CFLAGS) speedcheck.c | LINKLIBS = $(LINKLIBS) $(SSLLIBS) | ||||||
| sslusers.obj: ssluse.c | CC       = $(CCDEBUG) $(CFLAGSSSL) | ||||||
| 	$(CCRS) $(CFLAGS) ssluse.c | CFGSET   = TRUE | ||||||
| timevalrs.obj: timeval.c | !ENDIF | ||||||
| 	$(CCRS) $(CFLAGS) timeval.c |  | ||||||
| urlrs.obj: url.c | ####################### | ||||||
| 	$(CCRS) $(CFLAGS) url.c | # Usage | ||||||
| filers.obj: file.c | # | ||||||
| 	$(CCRS) $(CFLAGS) file.c | !IF "$(CFGSET)" == "FALSE" | ||||||
| getinfors.obj: getinfo.c | !MESSAGE Usage: nmake -f makefile.vc6 CFG=<config> <target> | ||||||
| 	$(CCRS) $(CFLAGS) getinfo.c | !MESSAGE where <config> is one of: | ||||||
| versionrs.obj: version.c | !MESSAGE   release          - release static library | ||||||
| 	$(CCRS) $(CFLAGS) version.c | !MESSAGE   release-dll      - release dll | ||||||
| easyrs.obj: easy.c | !MESSAGE   release-ssl      - release static library with ssl | ||||||
| 	$(CCRS) $(CFLAGS) easy.c | !MESSAGE   release-ssl-dll  - release dll library with ssl | ||||||
| strequalrs.obj: strequal.c | !MESSAGE   debug            - debug static library | ||||||
| 	$(CCRS) $(CFLAGS) strequal.c | !MESSAGE   debug-dll        - debug dll | ||||||
| strtokrs.obj:strtok.c | !MESSAGE   debug-ssl        - debug static library with ssl | ||||||
| 	$(CCRS) $(CFLAGS) strtok.c | !MESSAGE   debug-ssl-dll    - debug dll library with ssl | ||||||
| connectrs.obj:connect.c | !MESSAGE <target> can be left blank in which case all is assumed | ||||||
| 	$(CCR) $(CFLAGS) connect.c | !ERROR please choose a valid configuration "$(CFG)" | ||||||
|  | !ENDIF | ||||||
|  |  | ||||||
|  | ####################### | ||||||
|  | # | ||||||
|  | X_OBJS= \ | ||||||
|  | 	$(DIROBJ)\base64.obj \ | ||||||
|  | 	$(DIROBJ)\cookie.obj \ | ||||||
|  | 	$(DIROBJ)\transfer.obj \ | ||||||
|  | 	$(DIROBJ)\escape.obj \ | ||||||
|  | 	$(DIROBJ)\formdata.obj \ | ||||||
|  | 	$(DIROBJ)\ftp.obj \ | ||||||
|  | 	$(DIROBJ)\http.obj \ | ||||||
|  | 	$(DIROBJ)\http_chunks.obj \ | ||||||
|  | 	$(DIROBJ)\ldap.obj \ | ||||||
|  | 	$(DIROBJ)\dict.obj \ | ||||||
|  | 	$(DIROBJ)\telnet.obj \ | ||||||
|  | 	$(DIROBJ)\getdate.obj \ | ||||||
|  | 	$(DIROBJ)\getenv.obj \ | ||||||
|  | 	$(DIROBJ)\getpass.obj \ | ||||||
|  | 	$(DIROBJ)\hostip.obj \ | ||||||
|  | 	$(DIROBJ)\if2ip.obj \ | ||||||
|  | 	$(DIROBJ)\mprintf.obj \ | ||||||
|  | 	$(DIROBJ)\netrc.obj \ | ||||||
|  | 	$(DIROBJ)\progress.obj \ | ||||||
|  | 	$(DIROBJ)\sendf.obj \ | ||||||
|  | 	$(DIROBJ)\speedcheck.obj \ | ||||||
|  | 	$(DIROBJ)\ssluse.obj \ | ||||||
|  | 	$(DIROBJ)\timeval.obj \ | ||||||
|  | 	$(DIROBJ)\url.obj \ | ||||||
|  | 	$(DIROBJ)\file.obj \ | ||||||
|  | 	$(DIROBJ)\getinfo.obj \ | ||||||
|  | 	$(DIROBJ)\version.obj \ | ||||||
|  | 	$(DIROBJ)\easy.obj \ | ||||||
|  | 	$(DIROBJ)\strequal.obj \ | ||||||
|  | 	$(DIROBJ)\strtok.obj \ | ||||||
|  | 	$(DIROBJ)\connect.obj \ | ||||||
|  | 	$(DIROBJ)\hash.obj \ | ||||||
|  | 	$(DIROBJ)\llist.obj | ||||||
|  |  | ||||||
|  | all : $(TARGET) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | $(TARGET): $(X_OBJS) | ||||||
|  | 	$(LNK) $(LFLAGS) $(LINKLIBS) $(X_OBJS) | ||||||
|  |  | ||||||
|  | $(X_OBJS): $(DIROBJ) | ||||||
|  |  | ||||||
|  | $(DIROBJ): | ||||||
|  | 	@if not exist "$(DIROBJ)" mkdir $(DIROBJ) | ||||||
|  |  | ||||||
|  | .SUFFIXES: .c .obj | ||||||
|  |  | ||||||
|  | {.\}.c{$(DIROBJ)\}.obj: | ||||||
|  | 	$(CC) $(CFLAGS) /Fo"$@"  $< | ||||||
|  |  | ||||||
| clean: | clean: | ||||||
| 	-@erase *.obj | 	-@erase $(DIROBJ)\*.obj | ||||||
| 	-@erase vc60.idb | 	-@erase vc60.idb | ||||||
| 	-@erase vc60.pch | 	-@erase vc60.pch | ||||||
|  |  | ||||||
| distrib: clean |  | ||||||
| 	-@erase $(PROGRAM_NAME) |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ | |||||||
| static const char *telnetoptions[]= | static const char *telnetoptions[]= | ||||||
| { | { | ||||||
|   "BINARY",      "ECHO",           "RCP",           "SUPPRESS GO AHEAD", |   "BINARY",      "ECHO",           "RCP",           "SUPPRESS GO AHEAD", | ||||||
|   "NAME",        "STATUS"          "TIMING MARK",   "RCTE", |   "NAME",        "STATUS",         "TIMING MARK",   "RCTE", | ||||||
|   "NAOL",        "NAOP",           "NAOCRD",        "NAOHTS", |   "NAOL",        "NAOP",           "NAOCRD",        "NAOHTS", | ||||||
|   "NAOHTD",      "NAOFFD",         "NAOVTS",        "NAOVTD", |   "NAOHTD",      "NAOFFD",         "NAOVTS",        "NAOVTD", | ||||||
|   "NAOLFD",      "EXTEND ASCII",   "LOGOUT",        "BYTE MACRO", |   "NAOLFD",      "EXTEND ASCII",   "LOGOUT",        "BYTE MACRO", | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								lib/config-mac.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								lib/config-mac.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | #define OS "mac" | ||||||
|  |  | ||||||
|  | #define HAVE_NETINET_IN_H	1 | ||||||
|  | #define HAVE_SYS_SOCKET_H	1 | ||||||
|  | #define HAVE_SYS_SELECT_H	1 | ||||||
|  | #define HAVE_NETDB_H		1 | ||||||
|  | #define HAVE_ARPA_INET_H	1 | ||||||
|  | #define HAVE_UNISTD_H		1 | ||||||
|  | #define HAVE_NET_IF_H		1 | ||||||
|  | #define HAVE_SYS_TYPES_H	1 | ||||||
|  | #define HAVE_GETTIMEOFDAY	1 | ||||||
|  | #define HAVE_FCNTL_H		1 | ||||||
|  | #define HAVE_SYS_STAT_H		1 | ||||||
|  | #define HAVE_ALLOCA_H		1 | ||||||
|  | #define HAVE_TIME_H			1 | ||||||
|  | #define HAVE_STDLIB_H		1 | ||||||
|  | #define HAVE_UTIME_H		1 | ||||||
|  |  | ||||||
|  | #define TIME_WITH_SYS_TIME	1 | ||||||
|  |  | ||||||
|  | #define HAVE_STRDUP			1 | ||||||
|  | #define HAVE_UTIME			1 | ||||||
|  | #define HAVE_INET_NTOA		1 | ||||||
|  | #define HAVE_SETVBUF		1 | ||||||
|  | #define HAVE_STRFTIME		1 | ||||||
|  | #define HAVE_INET_ADDR		1 | ||||||
|  | #define HAVE_MEMCPY			1 | ||||||
|  | #define HAVE_SELECT			1 | ||||||
|  | #define HAVE_SOCKET			1 | ||||||
|  |  | ||||||
|  | //#define HAVE_STRICMP		1 | ||||||
|  | #define HAVE_SIGACTION		1 | ||||||
|  |  | ||||||
|  | #ifdef MACOS_SSL_SUPPORT | ||||||
|  | #	define USE_SSLEAY			1 | ||||||
|  | #	define USE_OPENSSL			1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define HAVE_RAND_STATUS	1 | ||||||
|  | #define HAVE_RAND_EGD		1 | ||||||
|  |  | ||||||
|  | #define HAVE_FIONBIO        1 | ||||||
|  |  | ||||||
|  | #include <extra/stricmp.h> | ||||||
|  | #include <extra/strdup.h> | ||||||
| @@ -221,22 +221,22 @@ | |||||||
| #define HAVE_NETINET_IN_H 1 | #define HAVE_NETINET_IN_H 1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/crypto.h> header file.  */ | /* Define if you have the <openssl/crypto.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_CRYPTO_H | #define HAVE_OPENSSL_CRYPTO_H 1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/err.h> header file.  */ | /* Define if you have the <openssl/err.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_ERR_H | #define HAVE_OPENSSL_ERR_H	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/pem.h> header file.  */ | /* Define if you have the <openssl/pem.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_PEM_H | #define HAVE_OPENSSL_PEM_H	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/rsa.h> header file.  */ | /* Define if you have the <openssl/rsa.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_RSA_H | #define HAVE_OPENSSL_RSA_H 1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/ssl.h> header file.  */ | /* Define if you have the <openssl/ssl.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_SSL_H | #define HAVE_OPENSSL_SSL_H	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <openssl/x509.h> header file.  */ | /* Define if you have the <openssl/x509.h> header file.  */ | ||||||
| #undef HAVE_OPENSSL_X509_H | #define HAVE_OPENSSL_X509_H	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the <pem.h> header file.  */ | /* Define if you have the <pem.h> header file.  */ | ||||||
| #undef HAVE_PEM_H | #undef HAVE_PEM_H | ||||||
| @@ -296,7 +296,7 @@ | |||||||
| #undef HAVE_X509_H | #undef HAVE_X509_H | ||||||
| 
 | 
 | ||||||
| /* Define if you have the crypto library (-lcrypto).  */ | /* Define if you have the crypto library (-lcrypto).  */ | ||||||
| #undef HAVE_LIBCRYPTO | #define HAVE_LIBCRYPTO 1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the dl library (-ldl).  */ | /* Define if you have the dl library (-ldl).  */ | ||||||
| #undef HAVE_LIBDL | #undef HAVE_LIBDL | ||||||
| @@ -314,7 +314,7 @@ | |||||||
| #define HAVE_LIBSOCKET 1 | #define HAVE_LIBSOCKET 1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the ssl library (-lssl).  */ | /* Define if you have the ssl library (-lssl).  */ | ||||||
| #undef HAVE_LIBSSL | #define HAVE_LIBSSL	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the ucb library (-lucb).  */ | /* Define if you have the ucb library (-lucb).  */ | ||||||
| #undef HAVE_LIBUCB | #undef HAVE_LIBUCB | ||||||
| @@ -346,7 +346,7 @@ | |||||||
| #undef HAVE_GETPASS | #undef HAVE_GETPASS | ||||||
| 
 | 
 | ||||||
| /* Define if you have a working OpenSSL installation */ | /* Define if you have a working OpenSSL installation */ | ||||||
| #undef OPENSSL_ENABLED | #define OPENSSL_ENABLED	1 | ||||||
| 
 | 
 | ||||||
| /* Define if you have the `dlopen' function. */ | /* Define if you have the `dlopen' function. */ | ||||||
| #undef HAVE_DLOPEN | #undef HAVE_DLOPEN | ||||||
| @@ -365,3 +365,4 @@ | |||||||
| 
 | 
 | ||||||
| #define HAVE_MEMORY_H   1 | #define HAVE_MEMORY_H   1 | ||||||
| 
 | 
 | ||||||
|  | #define HAVE_FIONBIO	1 | ||||||
| @@ -42,7 +42,7 @@ | |||||||
| #define SIZEOF_LONG_DOUBLE 16 | #define SIZEOF_LONG_DOUBLE 16 | ||||||
| 
 | 
 | ||||||
| /* The number of bytes in a long long.  */ | /* The number of bytes in a long long.  */ | ||||||
| #define SIZEOF_LONG_LONG 8 | /* #define SIZEOF_LONG_LONG 8 */ | ||||||
| 
 | 
 | ||||||
| /* Define if you have the gethostbyaddr function.  */ | /* Define if you have the gethostbyaddr function.  */ | ||||||
| #define HAVE_GETHOSTBYADDR 1 | #define HAVE_GETHOSTBYADDR 1 | ||||||
| @@ -179,6 +179,9 @@ | |||||||
| /* Define if you have the RAND_screen function when using SSL  */ | /* Define if you have the RAND_screen function when using SSL  */ | ||||||
| #define HAVE_RAND_SCREEN 1 | #define HAVE_RAND_SCREEN 1 | ||||||
| 
 | 
 | ||||||
|  | /* Define this to if in_addr_t is not an available typedefed type */ | ||||||
|  | #define in_addr_t unsigned long | ||||||
|  | 
 | ||||||
| /*************************************************
 | /*************************************************
 | ||||||
|  * This section is for compiler specific defines.* |  * This section is for compiler specific defines.* | ||||||
|  *************************************************/ |  *************************************************/ | ||||||
| @@ -44,6 +44,14 @@ | |||||||
| #ifdef HAVE_ARPA_INET_H | #ifdef HAVE_ARPA_INET_H | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
| #endif | #endif | ||||||
|  | #ifdef HAVE_STDLIB_H | ||||||
|  | #include <stdlib.h> /* required for free() prototype, without it, this crashes | ||||||
|  |                        on macos 68K */ | ||||||
|  | #endif | ||||||
|  | #ifdef	VMS | ||||||
|  | #include <in.h> | ||||||
|  | #include <inet.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| @@ -61,6 +69,7 @@ | |||||||
| #include <winsock.h> | #include <winsock.h> | ||||||
| #define EINPROGRESS WSAEINPROGRESS | #define EINPROGRESS WSAEINPROGRESS | ||||||
| #define EWOULDBLOCK WSAEWOULDBLOCK | #define EWOULDBLOCK WSAEWOULDBLOCK | ||||||
|  | #define EISCONN     WSAEISCONN | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| @@ -188,7 +197,7 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
| #ifdef HAVE_INET_NTOA | #ifdef HAVE_INET_NTOA | ||||||
|  |  | ||||||
| #ifndef INADDR_NONE | #ifndef INADDR_NONE | ||||||
| #define INADDR_NONE (unsigned long) ~0 | #define INADDR_NONE (in_addr_t) ~0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
| @@ -202,14 +211,14 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
|     char *hostdataptr=NULL; |     char *hostdataptr=NULL; | ||||||
|     size_t size; |     size_t size; | ||||||
|     char myhost[256] = ""; |     char myhost[256] = ""; | ||||||
|     unsigned long in; |     in_addr_t in; | ||||||
|  |  | ||||||
|     if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { |     if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { | ||||||
|       h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); |       h = Curl_resolv(data, myhost, 0, &hostdataptr); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       if(strlen(data->set.device)>1) { |       if(strlen(data->set.device)>1) { | ||||||
|         h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr); |         h = Curl_resolv(data, data->set.device, 0, &hostdataptr); | ||||||
|       } |       } | ||||||
|       if(h) { |       if(h) { | ||||||
|         /* we know data->set.device is shorter than the myhost array */ |         /* we know data->set.device is shorter than the myhost array */ | ||||||
| @@ -224,14 +233,13 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
|          hostent_buf, |          hostent_buf, | ||||||
|          sizeof(hostent_buf)); |          sizeof(hostent_buf)); | ||||||
|       */ |       */ | ||||||
|       if(hostdataptr) |  | ||||||
|         free(hostdataptr); /* allocated by Curl_getaddrinfo() */ |  | ||||||
|       return CURLE_HTTP_PORT_FAILED; |       return CURLE_HTTP_PORT_FAILED; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     infof(data, "We bind local end to %s\n", myhost); |     infof(data, "We bind local end to %s\n", myhost); | ||||||
|  |  | ||||||
|     if ( (in=inet_addr(myhost)) != INADDR_NONE ) { |     in=inet_addr(myhost); | ||||||
|  |     if (INADDR_NONE != in) { | ||||||
|  |  | ||||||
|       if ( h ) { |       if ( h ) { | ||||||
|         memset((char *)&sa, 0, sizeof(sa)); |         memset((char *)&sa, 0, sizeof(sa)); | ||||||
| @@ -279,7 +287,7 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
|             failf(data, "Insufficient kernel memory was available: %d", errno); |             failf(data, "Insufficient kernel memory was available: %d", errno); | ||||||
|             break; |             break; | ||||||
|           default: |           default: | ||||||
|             failf(data, "errno %d\n", errno); |             failf(data, "errno %d", errno); | ||||||
|             break; |             break; | ||||||
|           } /* end of switch(errno) */ |           } /* end of switch(errno) */ | ||||||
| 	 | 	 | ||||||
| @@ -298,9 +306,6 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
|       return CURLE_HTTP_PORT_FAILED; |       return CURLE_HTTP_PORT_FAILED; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(hostdataptr) |  | ||||||
|       free(hostdataptr); /* allocated by Curl_getaddrinfo() */ |  | ||||||
|  |  | ||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|  |  | ||||||
|   } /* end of device selection support */ |   } /* end of device selection support */ | ||||||
| @@ -309,9 +314,8 @@ static CURLcode bindlocal(struct connectdata *conn, | |||||||
|  |  | ||||||
|   return CURLE_HTTP_PORT_FAILED; |   return CURLE_HTTP_PORT_FAILED; | ||||||
| } | } | ||||||
| #else /* end of ipv4-specific section */ | #endif /* end of ipv4-specific section */ | ||||||
|  |  | ||||||
| /* we only use socketerror() on IPv6-enabled machines */ |  | ||||||
| static | static | ||||||
| int socketerror(int sockfd) | int socketerror(int sockfd) | ||||||
| { | { | ||||||
| @@ -324,7 +328,6 @@ int socketerror(int sockfd) | |||||||
|    |    | ||||||
|   return err; |   return err; | ||||||
| } | } | ||||||
| #endif |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * TCP connect to the given host with timeout, proxy or remote doesn't matter. |  * TCP connect to the given host with timeout, proxy or remote doesn't matter. | ||||||
| @@ -362,7 +365,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|  |  | ||||||
|     /* get the most strict timeout of the ones converted to milliseconds */ |     /* get the most strict timeout of the ones converted to milliseconds */ | ||||||
|     if(data->set.timeout && |     if(data->set.timeout && | ||||||
|        (data->set.timeout>data->set.connecttimeout)) |        (data->set.timeout < data->set.connecttimeout)) | ||||||
|       timeout_ms = data->set.timeout*1000; |       timeout_ms = data->set.timeout*1000; | ||||||
|     else |     else | ||||||
|       timeout_ms = data->set.connecttimeout*1000; |       timeout_ms = data->set.connecttimeout*1000; | ||||||
| @@ -370,10 +373,12 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|     /* subtract the passed time */ |     /* subtract the passed time */ | ||||||
|     timeout_ms -= (long)has_passed; |     timeout_ms -= (long)has_passed; | ||||||
|  |  | ||||||
|     if(timeout_ms < 0) |     if(timeout_ms < 0) { | ||||||
|       /* a precaution, no need to continue if time already is up */ |       /* a precaution, no need to continue if time already is up */ | ||||||
|  |       failf(data, "Connection time-out"); | ||||||
|       return CURLE_OPERATION_TIMEOUTED; |       return CURLE_OPERATION_TIMEOUTED; | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
| #ifdef ENABLE_IPV6 | #ifdef ENABLE_IPV6 | ||||||
|   /* |   /* | ||||||
| @@ -449,8 +454,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|       return CURLE_COULDNT_CONNECT; |       return CURLE_COULDNT_CONNECT; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* now disable the non-blocking mode again */ |     /* leave the socket in non-blocking mode */ | ||||||
|     Curl_nonblock(sockfd, FALSE); |  | ||||||
|  |  | ||||||
|     if(addr) |     if(addr) | ||||||
|       *addr = ai; /* the address we ended up connected to */ |       *addr = ai; /* the address we ended up connected to */ | ||||||
| @@ -525,6 +529,16 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if(0 == rc) { | ||||||
|  |       int err = socketerror(sockfd); | ||||||
|  |       if ((0 == err) || (EISCONN == err)) { | ||||||
|  |         /* we are connected, awesome! */ | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |       /* nope, not connected for real */ | ||||||
|  |       rc = -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if(0 != rc) { |     if(0 != rc) { | ||||||
|       /* get a new timeout for next attempt */ |       /* get a new timeout for next attempt */ | ||||||
|       after = Curl_tvnow(); |       after = Curl_tvnow(); | ||||||
| @@ -542,11 +556,11 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */ | |||||||
|     /* no good connect was made */ |     /* no good connect was made */ | ||||||
|     sclose(sockfd); |     sclose(sockfd); | ||||||
|     *sockconn = -1; |     *sockconn = -1; | ||||||
|  |     failf(data, "Couldn't connect to host"); | ||||||
|     return CURLE_COULDNT_CONNECT; |     return CURLE_COULDNT_CONNECT; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* now disable the non-blocking mode again */ |   /* leave the socket in non-blocking mode */ | ||||||
|   Curl_nonblock(sockfd, FALSE); |  | ||||||
|  |  | ||||||
|   if(addr) |   if(addr) | ||||||
|     /* this is the address we've connected to */ |     /* this is the address we've connected to */ | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ int Curl_nonblock(int socket,    /* operate on this */ | |||||||
|  |  | ||||||
| CURLcode Curl_connecthost(struct connectdata *conn, | CURLcode Curl_connecthost(struct connectdata *conn, | ||||||
|                           Curl_addrinfo *host, /* connect to this */ |                           Curl_addrinfo *host, /* connect to this */ | ||||||
|                           long port,      /* connect to this port number */ |                           int port,       /* connect to this port number */ | ||||||
|                           int *sockconn,  /* not set if error is returned */ |                           int *sockconn,  /* not set if error is returned */ | ||||||
|                           Curl_ipconnect **addr /* the one we used */ |                           Curl_ipconnect **addr /* the one we used */ | ||||||
|                           ); /*  index we used */ |                           ); /*  index we used */ | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								lib/cookie.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								lib/cookie.c
									
									
									
									
									
								
							| @@ -194,6 +194,11 @@ Curl_cookie_add(struct CookieInfo *c, | |||||||
|       while(ptr && *ptr && isspace((int)*ptr)) |       while(ptr && *ptr && isspace((int)*ptr)) | ||||||
|         ptr++; |         ptr++; | ||||||
|       semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ |       semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ | ||||||
|  |  | ||||||
|  |       if(!semiptr && *ptr) | ||||||
|  |         /* There are no more semicolons, but there's a final name=value pair | ||||||
|  |            coming up */ | ||||||
|  |         semiptr=ptr; | ||||||
|     } while(semiptr); |     } while(semiptr); | ||||||
|  |  | ||||||
|     if(NULL == co->domain) |     if(NULL == co->domain) | ||||||
| @@ -377,8 +382,15 @@ Curl_cookie_add(struct CookieInfo *c, | |||||||
|  |  | ||||||
|         free(co);   /* free the newly alloced memory */ |         free(co);   /* free the newly alloced memory */ | ||||||
|         co = clist; /* point to the previous struct instead */ |         co = clist; /* point to the previous struct instead */ | ||||||
|       } |  | ||||||
|  |  | ||||||
|  |         /* We have replaced a cookie, now skip the rest of the list but | ||||||
|  |            make sure the 'lastc' pointer is properly set */ | ||||||
|  |         do { | ||||||
|  |           lastc = clist; | ||||||
|  |           clist = clist->next; | ||||||
|  |         } while(clist); | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     lastc = clist; |     lastc = clist; | ||||||
|     clist = clist->next; |     clist = clist->next; | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ struct Cookie { | |||||||
|   char *value;       /* name = <this> */ |   char *value;       /* name = <this> */ | ||||||
|   char *path;	      /* path = <this> */ |   char *path;	      /* path = <this> */ | ||||||
|   char *domain;      /* domain = <this> */ |   char *domain;      /* domain = <this> */ | ||||||
|   time_t expires;    /* expires = <this> */ |   long expires;    /* expires = <this> */ | ||||||
|   char *expirestr;   /* the plain text version */ |   char *expirestr;   /* the plain text version */ | ||||||
|  |  | ||||||
|   char field1;       /* read from a cookie file, 1 => FALSE, 2=> TRUE */ |   char field1;       /* read from a cookie file, 1 => FALSE, 2=> TRUE */ | ||||||
|   | |||||||
| @@ -151,6 +151,10 @@ SOURCE=.\getpass.c | |||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|  |  | ||||||
|  | SOURCE=.\hash.c | ||||||
|  | # End Source File | ||||||
|  | # Begin Source File | ||||||
|  |  | ||||||
| SOURCE=.\hostip.c | SOURCE=.\hostip.c | ||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
| @@ -179,6 +183,10 @@ SOURCE=.\libcurl.def | |||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|  |  | ||||||
|  | SOURCE=.\llist.c | ||||||
|  | # End Source File | ||||||
|  | # Begin Source File | ||||||
|  |  | ||||||
| SOURCE=.\memdebug.c | SOURCE=.\memdebug.c | ||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|   | |||||||
| @@ -121,7 +121,7 @@ CURLcode Curl_dict(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|        |        | ||||||
|     if ((word == NULL) || (*word == (char)0)) { |     if ((word == NULL) || (*word == (char)0)) { | ||||||
|       failf(data, "lookup word is missing\n"); |       failf(data, "lookup word is missing"); | ||||||
|     } |     } | ||||||
|     if ((database == NULL) || (*database == (char)0)) { |     if ((database == NULL) || (*database == (char)0)) { | ||||||
|       database = (char *)"!"; |       database = (char *)"!"; | ||||||
| @@ -174,7 +174,7 @@ CURLcode Curl_dict(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|        |        | ||||||
|     if ((word == NULL) || (*word == (char)0)) { |     if ((word == NULL) || (*word == (char)0)) { | ||||||
|       failf(data, "lookup word is missing\n"); |       failf(data, "lookup word is missing"); | ||||||
|     } |     } | ||||||
|     if ((database == NULL) || (*database == (char)0)) { |     if ((database == NULL) || (*database == (char)0)) { | ||||||
|       database = (char *)"!"; |       database = (char *)"!"; | ||||||
|   | |||||||
| @@ -81,6 +81,10 @@ DllMain ( | |||||||
|     } |     } | ||||||
|   return TRUE; |   return TRUE; | ||||||
| } | } | ||||||
|  | #else | ||||||
|  | #ifdef VMS | ||||||
|  | int VOID_VAR_DLLINIT;	 | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								lib/easy.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								lib/easy.c
									
									
									
									
									
								
							| @@ -76,6 +76,7 @@ | |||||||
| #include "ssluse.h" | #include "ssluse.h" | ||||||
| #include "url.h" | #include "url.h" | ||||||
| #include "getinfo.h" | #include "getinfo.h" | ||||||
|  | #include "hostip.h" | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
| @@ -162,6 +163,8 @@ void curl_global_cleanup(void) | |||||||
|   if (!initialized) |   if (!initialized) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|  |   Curl_global_host_cache_dtor(); | ||||||
|  |  | ||||||
|   if (init_flags & CURL_GLOBAL_SSL) |   if (init_flags & CURL_GLOBAL_SSL) | ||||||
|     Curl_SSL_cleanup(); |     Curl_SSL_cleanup(); | ||||||
|  |  | ||||||
| @@ -230,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl) | |||||||
| { | { | ||||||
|   struct SessionHandle *data = (struct SessionHandle *)curl; |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |  | ||||||
|  |   if (!data->hostcache) { | ||||||
|  |     if (Curl_global_host_cache_use(data)) { | ||||||
|  |       data->hostcache = Curl_global_host_cache_get(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return Curl_perform(data); |   return Curl_perform(data); | ||||||
| } | } | ||||||
|  |  | ||||||
| void curl_easy_cleanup(CURL *curl) | void curl_easy_cleanup(CURL *curl) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = (struct SessionHandle *)curl; |   struct SessionHandle *data = (struct SessionHandle *)curl; | ||||||
|  |   if (!Curl_global_host_cache_use(data)) { | ||||||
|  |     curl_hash_destroy(data->hostcache); | ||||||
|  |   } | ||||||
|   Curl_close(data); |   Curl_close(data); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -235,7 +235,6 @@ int FormParse(char *input, | |||||||
| 	     | 	     | ||||||
| 	    if(2 != sscanf(type, "%127[^/]/%127[^,\n]", | 	    if(2 != sscanf(type, "%127[^/]/%127[^,\n]", | ||||||
| 			   major, minor)) { | 			   major, minor)) { | ||||||
| 	      fprintf(stderr, "Illegally formatted content-type field!\n"); |  | ||||||
|               free(contents); |               free(contents); | ||||||
| 	      return 2; /* illegal content-type syntax! */ | 	      return 2; /* illegal content-type syntax! */ | ||||||
| 	    } | 	    } | ||||||
| @@ -371,7 +370,6 @@ int FormParse(char *input, | |||||||
|  |  | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     fprintf(stderr, "Illegally formatted input field!\n"); |  | ||||||
|     free(contents); |     free(contents); | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
| @@ -402,6 +400,7 @@ static struct HttpPost * AddHttpPost (char * name, | |||||||
|                                      long contentslength, |                                      long contentslength, | ||||||
|                                      char *contenttype, |                                      char *contenttype, | ||||||
|                                      long flags, |                                      long flags, | ||||||
|  |                                      struct curl_slist* contentHeader, | ||||||
|                                      struct HttpPost *parent_post, |                                      struct HttpPost *parent_post, | ||||||
|                                      struct HttpPost **httppost, |                                      struct HttpPost **httppost, | ||||||
|                                      struct HttpPost **last_post) |                                      struct HttpPost **last_post) | ||||||
| @@ -415,6 +414,7 @@ static struct HttpPost * AddHttpPost (char * name, | |||||||
|     post->contents = value; |     post->contents = value; | ||||||
|     post->contentslength = contentslength; |     post->contentslength = contentslength; | ||||||
|     post->contenttype = contenttype; |     post->contenttype = contenttype; | ||||||
|  |     post->contentheader = contentHeader; | ||||||
|     post->flags = flags; |     post->flags = flags; | ||||||
|   } |   } | ||||||
|   else |   else | ||||||
| @@ -823,8 +823,22 @@ FORMcode FormAdd(struct HttpPost **httppost, | |||||||
| 	} | 	} | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|  |     case CURLFORM_CONTENTHEADER: | ||||||
|  |       { | ||||||
|  |         struct curl_slist* list = NULL; | ||||||
|  |         if( array_state ) | ||||||
|  |           list = (struct curl_slist*)array_value; | ||||||
|  |         else | ||||||
|  |           list = va_arg(params,struct curl_slist*); | ||||||
|  |          | ||||||
|  |         if( current_form->contentheader ) | ||||||
|  |           return_value = FORMADD_OPTION_TWICE; | ||||||
|  |         else | ||||||
|  |           current_form->contentheader = list; | ||||||
|  |          | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|     default: |     default: | ||||||
|       fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option); |  | ||||||
|       return_value = FORMADD_UNKNOWN_OPTION; |       return_value = FORMADD_UNKNOWN_OPTION; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -872,13 +886,16 @@ FORMcode FormAdd(struct HttpPost **httppost, | |||||||
|             break; |             break; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if ( (post = AddHttpPost(form->name, form->namelength, |         post = AddHttpPost(form->name, form->namelength, | ||||||
|                            form->value, form->contentslength, |                            form->value, form->contentslength, | ||||||
|                            form->contenttype, form->flags, |                            form->contenttype, form->flags, | ||||||
|  |                            form->contentheader, | ||||||
|                            post, httppost, |                            post, httppost, | ||||||
|                                  last_post)) == NULL) { |                            last_post); | ||||||
|  |          | ||||||
|  |         if(!post) | ||||||
|           return_value = FORMADD_MEMORY; |           return_value = FORMADD_MEMORY; | ||||||
|         } |  | ||||||
|         if (form->contenttype) |         if (form->contenttype) | ||||||
|           prevtype = form->contenttype; |           prevtype = form->contenttype; | ||||||
|       } |       } | ||||||
| @@ -923,7 +940,7 @@ static int AddFormData(struct FormData **formp, | |||||||
|     length = strlen((char *)line); |     length = strlen((char *)line); | ||||||
|  |  | ||||||
|   newform->line = (char *)malloc(length+1); |   newform->line = (char *)malloc(length+1); | ||||||
|   memcpy(newform->line, line, length+1); |   memcpy(newform->line, line, length); | ||||||
|   newform->length = length; |   newform->length = length; | ||||||
|   newform->line[length]=0; /* zero terminate for easier debugging */ |   newform->line[length]=0; /* zero terminate for easier debugging */ | ||||||
|    |    | ||||||
| @@ -1029,6 +1046,8 @@ struct FormData *Curl_getFormData(struct HttpPost *post, | |||||||
|   int size =0; |   int size =0; | ||||||
|   char *boundary; |   char *boundary; | ||||||
|   char *fileboundary=NULL; |   char *fileboundary=NULL; | ||||||
|  |   struct curl_slist* curList; | ||||||
|  |  | ||||||
|  |  | ||||||
|   if(!post) |   if(!post) | ||||||
|     return NULL; /* no input => no output! */ |     return NULL; /* no input => no output! */ | ||||||
| @@ -1046,8 +1065,11 @@ struct FormData *Curl_getFormData(struct HttpPost *post, | |||||||
|    |    | ||||||
|   do { |   do { | ||||||
|  |  | ||||||
|  |     if(size) | ||||||
|  |       size += AddFormDataf(&form, "\r\n"); | ||||||
|  |  | ||||||
|     /* boundary */ |     /* boundary */ | ||||||
|     size += AddFormDataf(&form, "\r\n--%s\r\n", boundary); |     size += AddFormDataf(&form, "--%s\r\n", boundary); | ||||||
|  |  | ||||||
|     size += AddFormData(&form, |     size += AddFormData(&form, | ||||||
|                         "Content-Disposition: form-data; name=\"", 0); |                         "Content-Disposition: form-data; name=\"", 0); | ||||||
| @@ -1090,6 +1112,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post, | |||||||
| 			     file->contenttype); | 			     file->contenttype); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       curList = file->contentheader; | ||||||
|  |       while( curList ) { | ||||||
|  |         /* Process the additional headers specified for this form */ | ||||||
|  |         size += AddFormDataf( &form, "\r\n%s", curList->data ); | ||||||
|  |         curList = curList->next; | ||||||
|  |       } | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|       /* The header Content-Transfer-Encoding: seems to confuse some receivers |       /* The header Content-Transfer-Encoding: seems to confuse some receivers | ||||||
|        * (like the built-in PHP engine). While I can't see any reason why it |        * (like the built-in PHP engine). While I can't see any reason why it | ||||||
| @@ -1126,10 +1155,13 @@ struct FormData *Curl_getFormData(struct HttpPost *post, | |||||||
| 	  } | 	  } | ||||||
|           if(fileread != stdin) |           if(fileread != stdin) | ||||||
|             fclose(fileread); |             fclose(fileread); | ||||||
| 	} else { |  | ||||||
| 	  size += AddFormData(&form, "[File wasn't found by client]", 0); |  | ||||||
| 	} | 	} | ||||||
|       } else { |         else { | ||||||
|  |           /* File wasn't found, add a nothing field! */ | ||||||
|  | 	  size += AddFormData(&form, "", 0); | ||||||
|  | 	} | ||||||
|  |       } | ||||||
|  |  else { | ||||||
| 	/* include the contents we got */ | 	/* include the contents we got */ | ||||||
| 	size += AddFormData(&form, post->contents, post->contentslength); | 	size += AddFormData(&form, post->contents, post->contentslength); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ typedef struct FormInfo { | |||||||
|   long contentslength; |   long contentslength; | ||||||
|   char *contenttype; |   char *contenttype; | ||||||
|   long flags; |   long flags; | ||||||
|  |   struct curl_slist* contentheader; | ||||||
|   struct FormInfo *more; |   struct FormInfo *more; | ||||||
| } FormInfo; | } FormInfo; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										307
									
								
								lib/ftp.c
									
									
									
									
									
								
							
							
						
						
									
										307
									
								
								lib/ftp.c
									
									
									
									
									
								
							| @@ -55,6 +55,7 @@ | |||||||
| #include <netdb.h> | #include <netdb.h> | ||||||
| #endif | #endif | ||||||
| #ifdef	VMS | #ifdef	VMS | ||||||
|  | #include <in.h> | ||||||
| #include <inet.h> | #include <inet.h> | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
| @@ -84,6 +85,10 @@ | |||||||
| #include "ssluse.h" | #include "ssluse.h" | ||||||
| #include "connect.h" | #include "connect.h" | ||||||
|  |  | ||||||
|  | #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) | ||||||
|  | #include "inet_ntoa_r.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
|  |  | ||||||
| @@ -193,10 +198,15 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|   int code=0; /* default "error code" to return */ |   int code=0; /* default "error code" to return */ | ||||||
|  |  | ||||||
| #define SELECT_OK       0 | #define SELECT_OK       0 | ||||||
| #define SELECT_ERROR   1 | #define SELECT_ERROR    1 /* select() problems */ | ||||||
| #define SELECT_TIMEOUT 2 | #define SELECT_TIMEOUT  2 /* took too long */ | ||||||
|  | #define SELECT_MEMORY   3 /* no available memory */ | ||||||
|  | #define SELECT_CALLBACK 4 /* aborted by callback */ | ||||||
|  |  | ||||||
|   int error = SELECT_OK; |   int error = SELECT_OK; | ||||||
|  |  | ||||||
|  |   struct FTP *ftp = conn->proto.ftp; | ||||||
|  |  | ||||||
|   if (ftpcode) |   if (ftpcode) | ||||||
|     *ftpcode = 0; /* 0 for errors */ |     *ftpcode = 0; /* 0 for errors */ | ||||||
|  |  | ||||||
| @@ -229,6 +239,7 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|     interval.tv_sec = timeout; |     interval.tv_sec = timeout; | ||||||
|     interval.tv_usec = 0; |     interval.tv_usec = 0; | ||||||
|  |  | ||||||
|  |     if(!ftp->cache) | ||||||
|       switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) { |       switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) { | ||||||
|       case -1: /* select() error, stop reading */ |       case -1: /* select() error, stop reading */ | ||||||
|         error = SELECT_ERROR; |         error = SELECT_ERROR; | ||||||
| @@ -239,13 +250,37 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|         failf(data, "Transfer aborted due to timeout"); |         failf(data, "Transfer aborted due to timeout"); | ||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
|  |         error = SELECT_OK; | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     if(SELECT_OK == error) { | ||||||
|       /* |       /* | ||||||
|        * This code previously didn't use the kerberos sec_read() code |        * This code previously didn't use the kerberos sec_read() code | ||||||
|        * to read, but when we use Curl_read() it may do so. Do confirm |        * to read, but when we use Curl_read() it may do so. Do confirm | ||||||
|        * that this is still ok and then remove this comment! |        * that this is still ok and then remove this comment! | ||||||
|        */ |        */ | ||||||
|       if(CURLE_OK != Curl_read(conn, sockfd, ptr, BUFSIZE-nread, &gotbytes)) |       if(ftp->cache) { | ||||||
|  |         /* we had data in the "cache", copy that instead of doing an actual | ||||||
|  |            read */ | ||||||
|  |         memcpy(ptr, ftp->cache, ftp->cache_size); | ||||||
|  |         gotbytes = ftp->cache_size; | ||||||
|  |         free(ftp->cache);    /* free the cache */ | ||||||
|  |         ftp->cache = NULL;   /* clear the pointer */ | ||||||
|  |         ftp->cache_size = 0; /* zero the size just in case */ | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         int res = Curl_read(conn, sockfd, ptr, | ||||||
|  |                             BUFSIZE-nread, &gotbytes); | ||||||
|  |         if(res < 0) | ||||||
|  |           /* EWOULDBLOCK */ | ||||||
|  |           continue; /* go looping again */ | ||||||
|  |  | ||||||
|  |         if(CURLE_OK != res) | ||||||
|           keepon = FALSE; |           keepon = FALSE; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if(!keepon) | ||||||
|  |         ; | ||||||
|       else if(gotbytes <= 0) { |       else if(gotbytes <= 0) { | ||||||
|         keepon = FALSE; |         keepon = FALSE; | ||||||
|         error = SELECT_ERROR; |         error = SELECT_ERROR; | ||||||
| @@ -263,6 +298,7 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|           if(*ptr=='\n') { |           if(*ptr=='\n') { | ||||||
|             /* a newline is CRLF in ftp-talk, so the CR is ignored as |             /* a newline is CRLF in ftp-talk, so the CR is ignored as | ||||||
|                the line isn't really terminated until the LF comes */ |                the line isn't really terminated until the LF comes */ | ||||||
|  |             CURLcode result; | ||||||
|  |  | ||||||
|             /* output debug output if that is requested */ |             /* output debug output if that is requested */ | ||||||
|             if(data->set.verbose) { |             if(data->set.verbose) { | ||||||
| @@ -271,6 +307,16 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|               /* no need to output LF here, it is part of the data */ |               /* no need to output LF here, it is part of the data */ | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             /* | ||||||
|  |              * We pass all response-lines to the callback function registered | ||||||
|  |              * for "headers". The response lines can be seen as a kind of | ||||||
|  |              * headers. | ||||||
|  |              */ | ||||||
|  |             result = Curl_client_write(data, CLIENTWRITE_HEADER, | ||||||
|  |                                        line_start, perline); | ||||||
|  |             if(result) | ||||||
|  |               return -SELECT_CALLBACK; | ||||||
|  |                                         | ||||||
| #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ | #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ | ||||||
| 			isdigit((int)line[2]) && (' ' == line[3])) | 			isdigit((int)line[2]) && (' ' == line[3])) | ||||||
|  |  | ||||||
| @@ -279,26 +325,41 @@ int Curl_GetFTPResponse(char *buf, | |||||||
|                * line to the start of the buffer and zero terminate, |                * line to the start of the buffer and zero terminate, | ||||||
|                * for old times sake (and krb4)! */ |                * for old times sake (and krb4)! */ | ||||||
|               char *meow; |               char *meow; | ||||||
|               int i; |               int n; | ||||||
|               for(meow=line_start, i=0; meow<ptr; meow++, i++) |               for(meow=line_start, n=0; meow<ptr; meow++, n++) | ||||||
|                 buf[i] = *meow; |                 buf[n] = *meow; | ||||||
|               meow[i]=0; /* zero terminate */ |               *meow=0; /* zero terminate */ | ||||||
|               keepon=FALSE; |               keepon=FALSE; | ||||||
|  |               line_start = ptr+1; /* advance pointer */ | ||||||
|  |               i++; /* skip this before getting out */ | ||||||
|               break; |               break; | ||||||
|             } |             } | ||||||
|             perline=0; /* line starts over here */ |             perline=0; /* line starts over here */ | ||||||
|             line_start = ptr+1; |             line_start = ptr+1; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |         if(!keepon && (i != gotbytes)) { | ||||||
|  |           /* We found the end of the response lines, but we didn't parse the | ||||||
|  |              full chunk of data we have read from the server. We therefore | ||||||
|  |              need to store the rest of the data to be checked on the next | ||||||
|  |              invoke as it may actually contain another end of response | ||||||
|  |              already!  Cleverly figured out by Eric Lavigne in December | ||||||
|  |              2001. */ | ||||||
|  |           ftp->cache_size = gotbytes - i; | ||||||
|  |           ftp->cache = (char *)malloc(ftp->cache_size); | ||||||
|  |           if(ftp->cache) | ||||||
|  |             memcpy(ftp->cache, line_start, ftp->cache_size); | ||||||
|  |           else | ||||||
|  |             return -SELECT_MEMORY; /**BANG**/ | ||||||
|         } |         } | ||||||
|       break; |       } /* there was data */ | ||||||
|     } /* switch */ |     } /* if(no error) */ | ||||||
|   } /* while there's buffer left and loop is requested */ |   } /* while there's buffer left and loop is requested */ | ||||||
|  |  | ||||||
|   if(!error) |   if(!error) | ||||||
|     code = atoi(buf); |     code = atoi(buf); | ||||||
|  |  | ||||||
| #if KRB4 | #ifdef KRB4 | ||||||
|   /* handle the security-oriented responses 6xx ***/ |   /* handle the security-oriented responses 6xx ***/ | ||||||
|   /* FIXME: some errorchecking perhaps... ***/ |   /* FIXME: some errorchecking perhaps... ***/ | ||||||
|   switch(code) { |   switch(code) { | ||||||
| @@ -558,6 +619,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn) | |||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
|   char *buf = data->state.buffer; /* this is our buffer */ |   char *buf = data->state.buffer; /* this is our buffer */ | ||||||
|   int ftpcode; |   int ftpcode; | ||||||
|  |   CURLcode result=CURLE_OK; | ||||||
|  |  | ||||||
|   if(data->set.upload) { |   if(data->set.upload) { | ||||||
|     if((-1 != data->set.infilesize) && (data->set.infilesize != *ftp->bytecountp)) { |     if((-1 != data->set.infilesize) && (data->set.infilesize != *ftp->bytecountp)) { | ||||||
| @@ -575,8 +637,12 @@ CURLcode Curl_ftp_done(struct connectdata *conn) | |||||||
|     else if(!conn->bits.resume_done && |     else if(!conn->bits.resume_done && | ||||||
|             !data->set.no_body && |             !data->set.no_body && | ||||||
|             (0 == *ftp->bytecountp)) { |             (0 == *ftp->bytecountp)) { | ||||||
|  |       /* We consider this an error, but there's no true FTP error received | ||||||
|  |          why we need to continue to "read out" the server response too. | ||||||
|  |          We don't want to leave a "waiting" server reply if we'll get told | ||||||
|  |          to make a second request on this same connection! */ | ||||||
|       failf(data, "No data was received!"); |       failf(data, "No data was received!"); | ||||||
|       return CURLE_FTP_COULDNT_RETR_FILE; |       result = CURLE_FTP_COULDNT_RETR_FILE; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -604,12 +670,10 @@ CURLcode Curl_ftp_done(struct connectdata *conn) | |||||||
|   conn->bits.resume_done = FALSE; /* clean this for next connection */ |   conn->bits.resume_done = FALSE; /* clean this for next connection */ | ||||||
|  |  | ||||||
|   /* Send any post-transfer QUOTE strings? */ |   /* Send any post-transfer QUOTE strings? */ | ||||||
|   if(data->set.postquote) { |   if(!result && data->set.postquote) | ||||||
|     CURLcode result = ftp_sendquote(conn, data->set.postquote); |     result = ftp_sendquote(conn, data->set.postquote); | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
| @@ -633,8 +697,7 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) | |||||||
|     if (item->data) { |     if (item->data) { | ||||||
|       FTPSENDF(conn, "%s", item->data); |       FTPSENDF(conn, "%s", item->data); | ||||||
|  |  | ||||||
|       nread = Curl_GetFTPResponse( |       nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode); | ||||||
|                                   conn->data->state.buffer, conn, &ftpcode); |  | ||||||
|       if (nread < 0) |       if (nread < 0) | ||||||
|         return CURLE_OPERATION_TIMEOUTED; |         return CURLE_OPERATION_TIMEOUTED; | ||||||
|  |  | ||||||
| @@ -810,24 +873,35 @@ ftp_pasv_verbose(struct connectdata *conn, | |||||||
| #ifdef HAVE_INET_NTOA_R | #ifdef HAVE_INET_NTOA_R | ||||||
|   char ntoa_buf[64]; |   char ntoa_buf[64]; | ||||||
| #endif | #endif | ||||||
|   char hostent_buf[8192]; |   /* The array size trick below is to make this a large chunk of memory | ||||||
|  |      suitably 8-byte aligned on 64-bit platforms. This was thoughtfully | ||||||
|  |      suggested by Philip Gladstone. */ | ||||||
|  |   long bigbuf[9000 / sizeof(long)]; | ||||||
|  |  | ||||||
| #if defined(HAVE_INET_ADDR) | #if defined(HAVE_INET_ADDR) | ||||||
|   unsigned long address; |   in_addr_t address; | ||||||
| # if defined(HAVE_GETHOSTBYADDR_R) | # if defined(HAVE_GETHOSTBYADDR_R) | ||||||
|   int h_errnop; |   int h_errnop; | ||||||
| # endif | # endif | ||||||
|  |   char *hostent_buf = (char *)bigbuf; /* get a char * to the buffer */ | ||||||
|  |  | ||||||
|   address = inet_addr(newhost); |   address = inet_addr(newhost); | ||||||
| # ifdef HAVE_GETHOSTBYADDR_R | # ifdef HAVE_GETHOSTBYADDR_R | ||||||
|  |  | ||||||
| #  ifdef HAVE_GETHOSTBYADDR_R_5 | #  ifdef HAVE_GETHOSTBYADDR_R_5 | ||||||
|   /* AIX, Digital Unix style: |   /* AIX, Digital Unix (OSF1, Tru64) style: | ||||||
|      extern int gethostbyaddr_r(char *addr, size_t len, int type, |      extern int gethostbyaddr_r(char *addr, size_t len, int type, | ||||||
|      struct hostent *htent, struct hostent_data *ht_data); */ |      struct hostent *htent, struct hostent_data *ht_data); */ | ||||||
|  |  | ||||||
|   /* Fred Noz helped me try this out, now it at least compiles! */ |   /* Fred Noz helped me try this out, now it at least compiles! */ | ||||||
|  |  | ||||||
|  |   /* Bjorn Reese (November 28 2001): | ||||||
|  |      The Tru64 man page on gethostbyaddr_r() says that | ||||||
|  |      the hostent struct must be filled with zeroes before the call to | ||||||
|  |      gethostbyaddr_r(). */ | ||||||
|  |  | ||||||
|  |   memset(hostent_buf, 0, sizeof(struct hostent)); | ||||||
|  |  | ||||||
|   if(gethostbyaddr_r((char *) &address, |   if(gethostbyaddr_r((char *) &address, | ||||||
|                      sizeof(address), AF_INET, |                      sizeof(address), AF_INET, | ||||||
|                      (struct hostent *)hostent_buf, |                      (struct hostent *)hostent_buf, | ||||||
| @@ -838,7 +912,7 @@ ftp_pasv_verbose(struct connectdata *conn, | |||||||
| #  ifdef HAVE_GETHOSTBYADDR_R_7 | #  ifdef HAVE_GETHOSTBYADDR_R_7 | ||||||
|   /* Solaris and IRIX */ |   /* Solaris and IRIX */ | ||||||
|   answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, |   answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, | ||||||
|                            (struct hostent *)hostent_buf, |                            (struct hostent *)bigbuf, | ||||||
|                            hostent_buf + sizeof(*answer), |                            hostent_buf + sizeof(*answer), | ||||||
|                            sizeof(hostent_buf) - sizeof(*answer), |                            sizeof(hostent_buf) - sizeof(*answer), | ||||||
|                            &h_errnop); |                            &h_errnop); | ||||||
| @@ -1125,30 +1199,30 @@ CURLcode ftp_use_port(struct connectdata *conn) | |||||||
|   struct sockaddr_in sa; |   struct sockaddr_in sa; | ||||||
|   struct hostent *h=NULL; |   struct hostent *h=NULL; | ||||||
|   char *hostdataptr=NULL; |   char *hostdataptr=NULL; | ||||||
|   size_t size; |  | ||||||
|   unsigned short porttouse; |   unsigned short porttouse; | ||||||
|   char myhost[256] = ""; |   char myhost[256] = ""; | ||||||
|  |  | ||||||
|   if(data->set.ftpport) { |   if(data->set.ftpport) { | ||||||
|     if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { |     if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { | ||||||
|       h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr); |       h = Curl_resolv(data, myhost, 0, &hostdataptr); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       if(strlen(data->set.ftpport)>1) |       int len = strlen(data->set.ftpport); | ||||||
|         h = Curl_getaddrinfo(data, data->set.ftpport, 0, &hostdataptr); |       if(len>1) | ||||||
|  |         h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr); | ||||||
|       if(h) |       if(h) | ||||||
|         strcpy(myhost, data->set.ftpport); /* buffer overflow risk */ |         strcpy(myhost, data->set.ftpport); /* buffer overflow risk */ | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if(! *myhost) { |   if(! *myhost) { | ||||||
|     h=Curl_getaddrinfo(data, |     char *tmp_host = getmyhost(myhost, sizeof(myhost)); | ||||||
|                        getmyhost(myhost, sizeof(myhost)), |     h=Curl_resolv(data, tmp_host, 0, &hostdataptr); | ||||||
|                        0, &hostdataptr); |  | ||||||
|   } |   } | ||||||
|   infof(data, "We connect from %s\n", myhost); |   infof(data, "We connect from %s\n", myhost); | ||||||
|    |    | ||||||
|   if ( h ) { |   if ( h ) { | ||||||
|     if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) { |     if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) { | ||||||
|  |       int size; | ||||||
|        |        | ||||||
|       /* we set the secondary socket variable to this for now, it |       /* we set the secondary socket variable to this for now, it | ||||||
|          is only so that the cleanup function will close it in case |          is only so that the cleanup function will close it in case | ||||||
| @@ -1167,10 +1241,10 @@ CURLcode ftp_use_port(struct connectdata *conn) | |||||||
|       if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) { |       if(bind(portsock, (struct sockaddr *)&sa, size) >= 0) { | ||||||
|         /* we succeeded to bind */ |         /* we succeeded to bind */ | ||||||
|         struct sockaddr_in add; |         struct sockaddr_in add; | ||||||
|         size = sizeof(add); |         socklen_t socksize = sizeof(add); | ||||||
|  |  | ||||||
|         if(getsockname(portsock, (struct sockaddr *) &add, |         if(getsockname(portsock, (struct sockaddr *) &add, | ||||||
|                        (socklen_t *)&size)<0) { |                        &socksize)<0) { | ||||||
|           failf(data, "getsockname() failed"); |           failf(data, "getsockname() failed"); | ||||||
|           return CURLE_FTP_PORT_FAILED; |           return CURLE_FTP_PORT_FAILED; | ||||||
|         } |         } | ||||||
| @@ -1193,9 +1267,6 @@ CURLcode ftp_use_port(struct connectdata *conn) | |||||||
|       free(hostdataptr); |       free(hostdataptr); | ||||||
|       return CURLE_FTP_PORT_FAILED; |       return CURLE_FTP_PORT_FAILED; | ||||||
|     } |     } | ||||||
|     if(hostdataptr) |  | ||||||
|       /* free the memory used for name lookup */ |  | ||||||
|       Curl_freeaddrinfo(hostdataptr); |  | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     failf(data, "could't find my own IP address (%s)", myhost); |     failf(data, "could't find my own IP address (%s)", myhost); | ||||||
| @@ -1256,23 +1327,53 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|   char *buf = data->state.buffer; /* this is our buffer */ |   char *buf = data->state.buffer; /* this is our buffer */ | ||||||
|   int ftpcode; /* receive FTP response codes in this */ |   int ftpcode; /* receive FTP response codes in this */ | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|  |   Curl_addrinfo *addr=NULL; | ||||||
|  |   Curl_ipconnect *conninfo; | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |     Here's the excecutive summary on what to do: | ||||||
|  |  | ||||||
|  |     PASV is RFC959, expect: | ||||||
|  |     227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) | ||||||
|  |  | ||||||
|  |     LPSV is RFC1639, expect: | ||||||
|  |     228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) | ||||||
|  |  | ||||||
|  |     EPSV is RFC2428, expect: | ||||||
|  |     229 Entering Extended Passive Mode (|||port|) | ||||||
|  |  | ||||||
|  |   */ | ||||||
|  |  | ||||||
|  | #if 1 | ||||||
|  |   const char *mode[] = { "EPSV", "PASV", NULL }; | ||||||
|  |   int results[] = { 229, 227, 0 }; | ||||||
|  | #else | ||||||
| #if 0 | #if 0 | ||||||
|   /* no support for IPv6 passive mode yet */ |  | ||||||
|   char *mode[] = { "EPSV", "LPSV", "PASV", NULL }; |   char *mode[] = { "EPSV", "LPSV", "PASV", NULL }; | ||||||
|   int results[] = { 229, 228, 227, 0 }; |   int results[] = { 229, 228, 227, 0 }; | ||||||
| #else | #else | ||||||
|   const char *mode[] = { "PASV", NULL }; |   const char *mode[] = { "PASV", NULL }; | ||||||
|   int results[] = { 227, 0 }; |   int results[] = { 227, 0 }; | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
|   int modeoff; |   int modeoff; | ||||||
|  |   unsigned short connectport; /* the local port connect() should use! */ | ||||||
|  |   unsigned short newport; /* remote port, not necessary the local one */ | ||||||
|  |   char *hostdataptr=NULL; | ||||||
|    |    | ||||||
|   for (modeoff = 0; mode[modeoff]; modeoff++) { |   /* newhost must be able to hold a full IP-style address in ASCII, which | ||||||
|     FTPSENDF(conn, mode[modeoff], ""); |      in the IPv6 case means 5*8-1 = 39 letters */ | ||||||
|  |   char newhost[48]; | ||||||
|  |   char *newhostp=NULL; | ||||||
|  |    | ||||||
|  |   for (modeoff = (data->set.ftp_use_epsv?0:1); | ||||||
|  |        mode[modeoff]; modeoff++) { | ||||||
|  |     result = Curl_ftpsendf(conn, mode[modeoff]); | ||||||
|  |     if(result) | ||||||
|  |       return result; | ||||||
|     nread = Curl_GetFTPResponse(buf, conn, &ftpcode); |     nread = Curl_GetFTPResponse(buf, conn, &ftpcode); | ||||||
|     if(nread < 0) |     if(nread < 0) | ||||||
|       return CURLE_OPERATION_TIMEOUTED; |       return CURLE_OPERATION_TIMEOUTED; | ||||||
|      |  | ||||||
|     if (ftpcode == results[modeoff]) |     if (ftpcode == results[modeoff]) | ||||||
|       break; |       break; | ||||||
|   } |   } | ||||||
| @@ -1281,16 +1382,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|     failf(data, "Odd return code after PASV"); |     failf(data, "Odd return code after PASV"); | ||||||
|     return CURLE_FTP_WEIRD_PASV_REPLY; |     return CURLE_FTP_WEIRD_PASV_REPLY; | ||||||
|   } |   } | ||||||
|   else if (strcmp(mode[modeoff], "PASV") == 0) { |   else if (227 == results[modeoff]) { | ||||||
|     int ip[4]; |     int ip[4]; | ||||||
|     int port[2]; |     int port[2]; | ||||||
|     unsigned short newport; /* remote port, not necessary the local one */ |  | ||||||
|     unsigned short connectport; /* the local port connect() should use! */ |  | ||||||
|     char newhost[32]; |  | ||||||
|      |  | ||||||
|     Curl_addrinfo *addr; |  | ||||||
|     char *hostdataptr=NULL; |  | ||||||
|     Curl_ipconnect *conninfo; |  | ||||||
|     char *str=buf; |     char *str=buf; | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
| @@ -1318,7 +1412,40 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); |     sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); | ||||||
|  |     newhostp = newhost; | ||||||
|     newport = (port[0]<<8) + port[1]; |     newport = (port[0]<<8) + port[1]; | ||||||
|  |   } | ||||||
|  | #if 1 | ||||||
|  |   else if (229 == results[modeoff]) { | ||||||
|  |     char *ptr = strchr(buf, '('); | ||||||
|  |     if(ptr) { | ||||||
|  |       unsigned int num; | ||||||
|  |       char separator[4]; | ||||||
|  |       ptr++; | ||||||
|  |       if(5  == sscanf(ptr, "%c%c%c%u%c", | ||||||
|  |                       &separator[0], | ||||||
|  |                       &separator[1], | ||||||
|  |                       &separator[2], | ||||||
|  |                       &num, | ||||||
|  |                       &separator[3])) { | ||||||
|  |         /* the four separators should be identical */ | ||||||
|  |         newport = num; | ||||||
|  |  | ||||||
|  |         /* we should use the same host we already are connected to */ | ||||||
|  |         newhostp = conn->name; | ||||||
|  |       }                       | ||||||
|  |       else | ||||||
|  |         ptr=NULL; | ||||||
|  |     } | ||||||
|  |     if(!ptr) { | ||||||
|  |       failf(data, "Weirdly formatted EPSV reply"); | ||||||
|  |       return CURLE_FTP_WEIRD_PASV_REPLY; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |   else | ||||||
|  |     return CURLE_FTP_CANT_RECONNECT; | ||||||
|  |  | ||||||
|   if(data->change.proxy) { |   if(data->change.proxy) { | ||||||
|     /* |     /* | ||||||
|      * This is a tunnel through a http proxy and we need to connect to the |      * This is a tunnel through a http proxy and we need to connect to the | ||||||
| @@ -1331,7 +1458,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     /* normal, direct, ftp connection */ |     /* normal, direct, ftp connection */ | ||||||
|       addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr); |     addr = Curl_resolv(data, newhostp, newport, &hostdataptr); | ||||||
|     if(!addr) { |     if(!addr) { | ||||||
|       failf(data, "Can't resolve new host %s", newhost); |       failf(data, "Can't resolve new host %s", newhost); | ||||||
|       return CURLE_FTP_CANT_GET_HOST; |       return CURLE_FTP_CANT_GET_HOST; | ||||||
| @@ -1350,9 +1477,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|     /* this just dumps information about this second connection */ |     /* this just dumps information about this second connection */ | ||||||
|     ftp_pasv_verbose(conn, conninfo, newhost, connectport); |     ftp_pasv_verbose(conn, conninfo, newhost, connectport); | ||||||
|    |    | ||||||
|     if(hostdataptr) |  | ||||||
|       Curl_freeaddrinfo(hostdataptr); |  | ||||||
|  |  | ||||||
|   if(CURLE_OK != result) |   if(CURLE_OK != result) | ||||||
|     return result; |     return result; | ||||||
|  |  | ||||||
| @@ -1363,9 +1487,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn) | |||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
|   } |   } | ||||||
|   } |  | ||||||
|   else |  | ||||||
|     return CURLE_FTP_CANT_RECONNECT; |  | ||||||
|  |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
| @@ -1420,9 +1541,10 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|       return result; |       return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* If we have selected NOBODY, it means that we only want file information. |   /* If we have selected NOBODY and HEADER, it means that we only want file | ||||||
|      Which in FTP can't be much more than the file size! */ |      information. Which in FTP can't be much more than the file size and | ||||||
|   if(data->set.no_body) { |      date. */ | ||||||
|  |   if(data->set.no_body && data->set.include_header) { | ||||||
|     /* The SIZE command is _not_ RFC 959 specified, and therefor many servers |     /* The SIZE command is _not_ RFC 959 specified, and therefor many servers | ||||||
|        may not support it! It is however the only way we have to get a file's |        may not support it! It is however the only way we have to get a file's | ||||||
|        size! */ |        size! */ | ||||||
| @@ -1454,7 +1576,7 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|       struct tm buffer; |       struct tm buffer; | ||||||
|       tm = (struct tm *)localtime_r(&data->info.filetime, &buffer); |       tm = (struct tm *)localtime_r(&data->info.filetime, &buffer); | ||||||
| #else | #else | ||||||
|       tm = localtime(&data->info.filetime); |       tm = localtime((unsigned long *)&data->info.filetime); | ||||||
| #endif | #endif | ||||||
|       /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ |       /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ | ||||||
|       strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n", |       strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n", | ||||||
| @@ -1468,20 +1590,27 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|     return CURLE_OK; |     return CURLE_OK; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   if(data->set.no_body) | ||||||
|  |     /* don't transfer the data */ | ||||||
|  |     ; | ||||||
|   /* Get us a second connection up and connected */ |   /* Get us a second connection up and connected */ | ||||||
|   if(data->set.ftp_use_port) |   else if(data->set.ftp_use_port) { | ||||||
|     /* We have chosen to use the PORT command */ |     /* We have chosen to use the PORT command */ | ||||||
|     result = ftp_use_port(conn); |     result = ftp_use_port(conn); | ||||||
|   else |     if(CURLE_OK == result) | ||||||
|  |       /* we have the data connection ready */ | ||||||
|  |       infof(data, "Connected the data stream with PORT!\n"); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|     /* We have chosen (this is default) to use the PASV command */ |     /* We have chosen (this is default) to use the PASV command */ | ||||||
|     result = ftp_use_pasv(conn); |     result = ftp_use_pasv(conn); | ||||||
|  |     if(CURLE_OK == result) | ||||||
|  |       infof(data, "Connected the data stream with PASV!\n"); | ||||||
|  |   } | ||||||
|    |    | ||||||
|   if(result) |   if(result) | ||||||
|     return result; |     return result; | ||||||
|  |  | ||||||
|   /* we have the data connection ready */ |  | ||||||
|   infof(data, "Connected the data stream!\n"); |  | ||||||
|  |  | ||||||
|   if(data->set.upload) { |   if(data->set.upload) { | ||||||
|  |  | ||||||
|     /* Set type to binary (unless specified ASCII) */ |     /* Set type to binary (unless specified ASCII) */ | ||||||
| @@ -1506,11 +1635,13 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|       if(conn->resume_from < 0 ) { |       if(conn->resume_from < 0 ) { | ||||||
|         /* we could've got a specified offset from the command line, |         /* we could've got a specified offset from the command line, | ||||||
|            but now we know we didn't */ |            but now we know we didn't */ | ||||||
|  |         ssize_t gottensize; | ||||||
|  |  | ||||||
|         if(CURLE_OK != ftp_getsize(conn, ftp->file, &conn->resume_from)) { |         if(CURLE_OK != ftp_getsize(conn, ftp->file, &gottensize)) { | ||||||
|           failf(data, "Couldn't get remote file size"); |           failf(data, "Couldn't get remote file size"); | ||||||
|           return CURLE_FTP_COULDNT_GET_SIZE; |           return CURLE_FTP_COULDNT_GET_SIZE; | ||||||
|         } |         } | ||||||
|  |         conn->resume_from = gottensize; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(conn->resume_from) { |       if(conn->resume_from) { | ||||||
| @@ -1535,7 +1666,7 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|  |  | ||||||
|           passed += actuallyread; |           passed += actuallyread; | ||||||
|           if(actuallyread != readthisamountnow) { |           if(actuallyread != readthisamountnow) { | ||||||
|             failf(data, "Could only read %d bytes from the input\n", passed); |             failf(data, "Could only read %d bytes from the input", passed); | ||||||
|             return CURLE_FTP_COULDNT_USE_REST; |             return CURLE_FTP_COULDNT_USE_REST; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -1602,7 +1733,7 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|       return result; |       return result; | ||||||
|        |        | ||||||
|   } |   } | ||||||
|   else { |   else if(!data->set.no_body) { | ||||||
|     /* Retrieve file or directory */ |     /* Retrieve file or directory */ | ||||||
|     bool dirlist=FALSE; |     bool dirlist=FALSE; | ||||||
|     long downloadsize=-1; |     long downloadsize=-1; | ||||||
| @@ -1665,22 +1796,32 @@ CURLcode ftp_perform(struct connectdata *conn) | |||||||
|             (data->set.ftp_list_only?"NLST":"LIST")); |             (data->set.ftp_list_only?"NLST":"LIST")); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|  |       ssize_t foundsize; | ||||||
|  |  | ||||||
|       /* Set type to binary (unless specified ASCII) */ |       /* Set type to binary (unless specified ASCII) */ | ||||||
|       result = ftp_transfertype(conn, data->set.ftp_ascii); |       result = ftp_transfertype(conn, data->set.ftp_ascii); | ||||||
|       if(result) |       if(result) | ||||||
|         return result; |         return result; | ||||||
|  |  | ||||||
|  |       /* Attempt to get the size, it'll be useful in some cases: for resumed | ||||||
|  |          downloads and when talking to servers that don't give away the size | ||||||
|  |          in the RETR response line. */ | ||||||
|  |       result = ftp_getsize(conn, ftp->file, &foundsize); | ||||||
|  |       if(CURLE_OK == result) | ||||||
|  |         downloadsize = foundsize; | ||||||
|  |  | ||||||
|       if(conn->resume_from) { |       if(conn->resume_from) { | ||||||
|  |  | ||||||
|         /* Daniel: (August 4, 1999) |         /* Daniel: (August 4, 1999) | ||||||
|          * |          * | ||||||
|          * We start with trying to use the SIZE command to figure out the size |          * We start with trying to use the SIZE command to figure out the size | ||||||
|          * of the file we're gonna get. If we can get the size, this is by far |          * of the file we're gonna get. If we can get the size, this is by far | ||||||
|          * the best way to know if we're trying to resume beyond the EOF.  */ |          * the best way to know if we're trying to resume beyond the EOF. | ||||||
|         int foundsize=-1; |          * | ||||||
|          |          * Daniel, November 28, 2001. We *always* get the size on downloads | ||||||
|         result = ftp_getsize(conn, ftp->file, &foundsize); |          * now, so it is done before this even when not doing resumes. I saved | ||||||
|  |          * the comment above for nostalgical reasons! ;-) | ||||||
|  |          */ | ||||||
|         if(CURLE_OK != result) { |         if(CURLE_OK != result) { | ||||||
|           infof(data, "ftp server doesn't support SIZE\n"); |           infof(data, "ftp server doesn't support SIZE\n"); | ||||||
|           /* We couldn't get the size and therefore we can't know if there |           /* We couldn't get the size and therefore we can't know if there | ||||||
| @@ -1918,9 +2059,11 @@ CURLcode Curl_ftp(struct connectdata *conn) | |||||||
| CURLcode Curl_ftpsendf(struct connectdata *conn, | CURLcode Curl_ftpsendf(struct connectdata *conn, | ||||||
|                        const char *fmt, ...) |                        const char *fmt, ...) | ||||||
| { | { | ||||||
|   size_t bytes_written; |   ssize_t bytes_written; | ||||||
|   char s[256]; |   char s[256]; | ||||||
|   size_t write_len; |   ssize_t write_len; | ||||||
|  |   char *sptr=s; | ||||||
|  |   CURLcode res = CURLE_OK; | ||||||
|  |  | ||||||
|   va_list ap; |   va_list ap; | ||||||
|   va_start(ap, fmt); |   va_start(ap, fmt); | ||||||
| @@ -1934,9 +2077,23 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, | |||||||
|  |  | ||||||
|   bytes_written=0; |   bytes_written=0; | ||||||
|   write_len = strlen(s); |   write_len = strlen(s); | ||||||
|   Curl_write(conn, conn->firstsocket, s, write_len, &bytes_written); |  | ||||||
|  |  | ||||||
|   return (bytes_written==write_len)?CURLE_OK:CURLE_WRITE_ERROR; |   do { | ||||||
|  |     res = Curl_write(conn, conn->firstsocket, sptr, write_len, | ||||||
|  |                      &bytes_written); | ||||||
|  |  | ||||||
|  |     if(CURLE_OK != res) | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |     if(bytes_written != write_len) { | ||||||
|  |       write_len -= bytes_written; | ||||||
|  |       sptr += bytes_written; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       break; | ||||||
|  |   } while(1); | ||||||
|  |  | ||||||
|  |   return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
| @@ -1954,6 +2111,8 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn) | |||||||
|   if(ftp) { |   if(ftp) { | ||||||
|     if(ftp->entrypath) |     if(ftp->entrypath) | ||||||
|       free(ftp->entrypath); |       free(ftp->entrypath); | ||||||
|  |     if(ftp->cache) | ||||||
|  |       free(ftp->cache); | ||||||
|   } |   } | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn); | |||||||
| CURLcode Curl_ftp_connect(struct connectdata *conn); | CURLcode Curl_ftp_connect(struct connectdata *conn); | ||||||
| CURLcode Curl_ftp_disconnect(struct connectdata *conn); | CURLcode Curl_ftp_disconnect(struct connectdata *conn); | ||||||
|  |  | ||||||
| size_t Curl_ftpsendf(struct connectdata *, const char *fmt, ...); | CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...); | ||||||
|  |  | ||||||
| /* The kerberos stuff needs this: */ | /* The kerberos stuff needs this: */ | ||||||
| int Curl_GetFTPResponse(char *buf, struct connectdata *conn, | int Curl_GetFTPResponse(char *buf, struct connectdata *conn, | ||||||
|   | |||||||
							
								
								
									
										523
									
								
								lib/getdate.c
									
									
									
									
									
								
							
							
						
						
									
										523
									
								
								lib/getdate.c
									
									
									
									
									
								
							| @@ -34,8 +34,6 @@ | |||||||
|  |  | ||||||
| #include "setup.h" | #include "setup.h" | ||||||
|  |  | ||||||
| #ifdef HAVE_CONFIG_H |  | ||||||
| # include "config.h" |  | ||||||
| # ifdef HAVE_ALLOCA_H | # ifdef HAVE_ALLOCA_H | ||||||
| #  include <alloca.h> | #  include <alloca.h> | ||||||
| # endif | # endif | ||||||
| @@ -43,6 +41,10 @@ | |||||||
| # ifdef HAVE_TIME_H | # ifdef HAVE_TIME_H | ||||||
| #  include <time.h> | #  include <time.h> | ||||||
| # endif | # endif | ||||||
|  |  | ||||||
|  | #ifndef YYDEBUG | ||||||
|  |   /* to satisfy gcc -Wundef, we set this to 0 */ | ||||||
|  | #define YYDEBUG 0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Since the code of getdate.y is not included in the Emacs executable | /* Since the code of getdate.y is not included in the Emacs executable | ||||||
| @@ -192,38 +194,40 @@ typedef enum _MERIDIAN { | |||||||
|     MERam, MERpm, MER24 |     MERam, MERpm, MER24 | ||||||
| } MERIDIAN; | } MERIDIAN; | ||||||
|  |  | ||||||
|  | /* parse results and input string */ | ||||||
|  | typedef struct _CONTEXT { | ||||||
|  |     const char	*yyInput; | ||||||
|  |     int		yyDayOrdinal; | ||||||
|  |     int		yyDayNumber; | ||||||
|  |     int		yyHaveDate; | ||||||
|  |     int		yyHaveDay; | ||||||
|  |     int		yyHaveRel; | ||||||
|  |     int		yyHaveTime; | ||||||
|  |     int		yyHaveZone; | ||||||
|  |     int		yyTimezone; | ||||||
|  |     int		yyDay; | ||||||
|  |     int		yyHour; | ||||||
|  |     int		yyMinutes; | ||||||
|  |     int		yyMonth; | ||||||
|  |     int		yySeconds; | ||||||
|  |     int		yyYear; | ||||||
|  |     MERIDIAN	yyMeridian; | ||||||
|  |     int		yyRelDay; | ||||||
|  |     int		yyRelHour; | ||||||
|  |     int		yyRelMinutes; | ||||||
|  |     int		yyRelMonth; | ||||||
|  |     int		yyRelSeconds; | ||||||
|  |     int		yyRelYear; | ||||||
|  | } CONTEXT; | ||||||
|  |  | ||||||
| /* | /* enable use of extra argument to yyparse and yylex which can be used to pass | ||||||
| **  Global variables.  We could get rid of most of these by using a good | **  in a user defined value (CONTEXT struct in our case) | ||||||
| **  union as the yacc stack.  (This routine was originally written before |  | ||||||
| **  yacc had the %union construct.)  Maybe someday; right now we only use |  | ||||||
| **  the %union very rarely. |  | ||||||
| */ | */ | ||||||
| static const char	*yyInput; | #define YYPARSE_PARAM cookie | ||||||
| static int	yyDayOrdinal; | #define YYLEX_PARAM cookie | ||||||
| static int	yyDayNumber; | #define context ((CONTEXT *) cookie) | ||||||
| static int	yyHaveDate; |  | ||||||
| static int	yyHaveDay; |  | ||||||
| static int	yyHaveRel; |  | ||||||
| static int	yyHaveTime; |  | ||||||
| static int	yyHaveZone; |  | ||||||
| static int	yyTimezone; |  | ||||||
| static int	yyDay; |  | ||||||
| static int	yyHour; |  | ||||||
| static int	yyMinutes; |  | ||||||
| static int	yyMonth; |  | ||||||
| static int	yySeconds; |  | ||||||
| static int	yyYear; |  | ||||||
| static MERIDIAN	yyMeridian; |  | ||||||
| static int	yyRelDay; |  | ||||||
| static int	yyRelHour; |  | ||||||
| static int	yyRelMinutes; |  | ||||||
| static int	yyRelMonth; |  | ||||||
| static int	yyRelSeconds; |  | ||||||
| static int	yyRelYear; |  | ||||||
|  |  | ||||||
|  | #line 215 "getdate.y" | ||||||
| #line 206 "getdate.y" |  | ||||||
| typedef union { | typedef union { | ||||||
|     int			Number; |     int			Number; | ||||||
|     enum _MERIDIAN	Meridian; |     enum _MERIDIAN	Meridian; | ||||||
| @@ -306,11 +310,11 @@ static const short yyrhs[] = {    -1, | |||||||
|  |  | ||||||
| #if YYDEBUG != 0 | #if YYDEBUG != 0 | ||||||
| static const short yyrline[] = { 0, | static const short yyrline[] = { 0, | ||||||
|    222,   223,   226,   229,   232,   235,   238,   241,   244,   250, |    231,   232,   235,   238,   241,   244,   247,   250,   253,   259, | ||||||
|    256,   265,   271,   283,   286,   289,   295,   299,   303,   309, |    265,   274,   280,   292,   295,   298,   304,   308,   312,   318, | ||||||
|    313,   331,   337,   343,   347,   352,   356,   363,   371,   374, |    322,   340,   346,   352,   356,   361,   365,   372,   380,   383, | ||||||
|    377,   380,   383,   386,   389,   392,   395,   398,   401,   404, |    386,   389,   392,   395,   398,   401,   404,   407,   410,   413, | ||||||
|    407,   410,   413,   416,   419,   422,   425,   430,   463,   467 |    416,   419,   422,   425,   428,   431,   434,   439,   473,   477 | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -390,6 +394,8 @@ static const short yycheck[] = {     0, | |||||||
|     11,    15,    13,    14,    16,    19,    17,    16,    21,     0, |     11,    15,    13,    14,    16,    19,    17,    16,    21,     0, | ||||||
|     56 |     56 | ||||||
| }; | }; | ||||||
|  | #define YYPURE 1 | ||||||
|  |  | ||||||
| /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */ | /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */ | ||||||
| #line 3 "/usr/local/share/bison.simple" | #line 3 "/usr/local/share/bison.simple" | ||||||
| /* This file comes from bison-1.28.  */ | /* This file comes from bison-1.28.  */ | ||||||
| @@ -934,135 +940,135 @@ yyreduce: | |||||||
|   switch (yyn) { |   switch (yyn) { | ||||||
|  |  | ||||||
| case 3: | case 3: | ||||||
| #line 226 "getdate.y" | #line 235 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHaveTime++; | 	    context->yyHaveTime++; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 4: | case 4: | ||||||
| #line 229 "getdate.y" | #line 238 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 5: | case 5: | ||||||
| #line 232 "getdate.y" | #line 241 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHaveDate++; | 	    context->yyHaveDate++; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 6: | case 6: | ||||||
| #line 235 "getdate.y" | #line 244 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHaveDay++; | 	    context->yyHaveDay++; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 7: | case 7: | ||||||
| #line 238 "getdate.y" | #line 247 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHaveRel++; | 	    context->yyHaveRel++; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 9: | case 9: | ||||||
| #line 244 "getdate.y" | #line 253 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHour = yyvsp[-1].Number; | 	    context->yyHour = yyvsp[-1].Number; | ||||||
| 	    yyMinutes = 0; | 	    context->yyMinutes = 0; | ||||||
| 	    yySeconds = 0; | 	    context->yySeconds = 0; | ||||||
| 	    yyMeridian = yyvsp[0].Meridian; | 	    context->yyMeridian = yyvsp[0].Meridian; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 10: | case 10: | ||||||
| #line 250 "getdate.y" | #line 259 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHour = yyvsp[-3].Number; | 	    context->yyHour = yyvsp[-3].Number; | ||||||
| 	    yyMinutes = yyvsp[-1].Number; | 	    context->yyMinutes = yyvsp[-1].Number; | ||||||
| 	    yySeconds = 0; | 	    context->yySeconds = 0; | ||||||
| 	    yyMeridian = yyvsp[0].Meridian; | 	    context->yyMeridian = yyvsp[0].Meridian; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 11: | case 11: | ||||||
| #line 256 "getdate.y" | #line 265 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHour = yyvsp[-3].Number; | 	    context->yyHour = yyvsp[-3].Number; | ||||||
| 	    yyMinutes = yyvsp[-1].Number; | 	    context->yyMinutes = yyvsp[-1].Number; | ||||||
| 	    yyMeridian = MER24; | 	    context->yyMeridian = MER24; | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	    yyTimezone = (yyvsp[0].Number < 0 | 	    context->yyTimezone = (yyvsp[0].Number < 0 | ||||||
| 				   ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 | 				   ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 | ||||||
| 				   : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); | 				   : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 12: | case 12: | ||||||
| #line 265 "getdate.y" | #line 274 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHour = yyvsp[-5].Number; | 	    context->yyHour = yyvsp[-5].Number; | ||||||
| 	    yyMinutes = yyvsp[-3].Number; | 	    context->yyMinutes = yyvsp[-3].Number; | ||||||
| 	    yySeconds = yyvsp[-1].Number; | 	    context->yySeconds = yyvsp[-1].Number; | ||||||
| 	    yyMeridian = yyvsp[0].Meridian; | 	    context->yyMeridian = yyvsp[0].Meridian; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 13: | case 13: | ||||||
| #line 271 "getdate.y" | #line 280 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyHour = yyvsp[-5].Number; | 	    context->yyHour = yyvsp[-5].Number; | ||||||
| 	    yyMinutes = yyvsp[-3].Number; | 	    context->yyMinutes = yyvsp[-3].Number; | ||||||
| 	    yySeconds = yyvsp[-1].Number; | 	    context->yySeconds = yyvsp[-1].Number; | ||||||
| 	    yyMeridian = MER24; | 	    context->yyMeridian = MER24; | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	    yyTimezone = (yyvsp[0].Number < 0 | 	    context->yyTimezone = (yyvsp[0].Number < 0 | ||||||
| 				   ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 | 				   ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 | ||||||
| 				   : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); | 				   : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 14: | case 14: | ||||||
| #line 283 "getdate.y" | #line 292 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyTimezone = yyvsp[0].Number; | 	    context->yyTimezone = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 15: | case 15: | ||||||
| #line 286 "getdate.y" | #line 295 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyTimezone = yyvsp[0].Number - 60; | 	    context->yyTimezone = yyvsp[0].Number - 60; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 16: | case 16: | ||||||
| #line 290 "getdate.y" | #line 299 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyTimezone = yyvsp[-1].Number - 60; | 	    context->yyTimezone = yyvsp[-1].Number - 60; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 17: | case 17: | ||||||
| #line 295 "getdate.y" | #line 304 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyDayOrdinal = 1; | 	    context->yyDayOrdinal = 1; | ||||||
| 	    yyDayNumber = yyvsp[0].Number; | 	    context->yyDayNumber = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 18: | case 18: | ||||||
| #line 299 "getdate.y" | #line 308 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyDayOrdinal = 1; | 	    context->yyDayOrdinal = 1; | ||||||
| 	    yyDayNumber = yyvsp[-1].Number; | 	    context->yyDayNumber = yyvsp[-1].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 19: | case 19: | ||||||
| #line 303 "getdate.y" | #line 312 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyDayOrdinal = yyvsp[-1].Number; | 	    context->yyDayOrdinal = yyvsp[-1].Number; | ||||||
| 	    yyDayNumber = yyvsp[0].Number; | 	    context->yyDayNumber = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 20: | case 20: | ||||||
| #line 309 "getdate.y" | #line 318 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyMonth = yyvsp[-2].Number; | 	    context->yyMonth = yyvsp[-2].Number; | ||||||
| 	    yyDay = yyvsp[0].Number; | 	    context->yyDay = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 21: | case 21: | ||||||
| #line 313 "getdate.y" | #line 322 "getdate.y" | ||||||
| { | { | ||||||
| 	  /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. | 	  /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. | ||||||
| 	     The goal in recognizing YYYY/MM/DD is solely to support legacy | 	     The goal in recognizing YYYY/MM/DD is solely to support legacy | ||||||
| @@ -1070,226 +1076,227 @@ case 21: | |||||||
| 	     you want portability, use the ISO 8601 format.  */ | 	     you want portability, use the ISO 8601 format.  */ | ||||||
| 	  if (yyvsp[-4].Number >= 1000) | 	  if (yyvsp[-4].Number >= 1000) | ||||||
| 	    { | 	    { | ||||||
| 	      yyYear = yyvsp[-4].Number; | 	      context->yyYear = yyvsp[-4].Number; | ||||||
| 	      yyMonth = yyvsp[-2].Number; | 	      context->yyMonth = yyvsp[-2].Number; | ||||||
| 	      yyDay = yyvsp[0].Number; | 	      context->yyDay = yyvsp[0].Number; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
| 	      yyMonth = yyvsp[-4].Number; | 	      context->yyMonth = yyvsp[-4].Number; | ||||||
| 	      yyDay = yyvsp[-2].Number; | 	      context->yyDay = yyvsp[-2].Number; | ||||||
| 	      yyYear = yyvsp[0].Number; | 	      context->yyYear = yyvsp[0].Number; | ||||||
| 	    } | 	    } | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 22: | case 22: | ||||||
| #line 331 "getdate.y" | #line 340 "getdate.y" | ||||||
| { | { | ||||||
| 	    /* ISO 8601 format.  yyyy-mm-dd.  */ | 	    /* ISO 8601 format.  yyyy-mm-dd.  */ | ||||||
| 	    yyYear = yyvsp[-2].Number; | 	    context->yyYear = yyvsp[-2].Number; | ||||||
| 	    yyMonth = -yyvsp[-1].Number; | 	    context->yyMonth = -yyvsp[-1].Number; | ||||||
| 	    yyDay = -yyvsp[0].Number; | 	    context->yyDay = -yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 23: | case 23: | ||||||
| #line 337 "getdate.y" | #line 346 "getdate.y" | ||||||
| { | { | ||||||
| 	    /* e.g. 17-JUN-1992.  */ | 	    /* e.g. 17-JUN-1992.  */ | ||||||
| 	    yyDay = yyvsp[-2].Number; | 	    context->yyDay = yyvsp[-2].Number; | ||||||
| 	    yyMonth = yyvsp[-1].Number; | 	    context->yyMonth = yyvsp[-1].Number; | ||||||
| 	    yyYear = -yyvsp[0].Number; | 	    context->yyYear = -yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 24: | case 24: | ||||||
| #line 343 "getdate.y" | #line 352 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyMonth = yyvsp[-1].Number; | 	    context->yyMonth = yyvsp[-1].Number; | ||||||
| 	    yyDay = yyvsp[0].Number; | 	    context->yyDay = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 25: | case 25: | ||||||
| #line 347 "getdate.y" | #line 356 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyMonth = yyvsp[-3].Number; | 	    context->yyMonth = yyvsp[-3].Number; | ||||||
| 	    yyDay = yyvsp[-2].Number; | 	    context->yyDay = yyvsp[-2].Number; | ||||||
| 	    yyYear = yyvsp[0].Number; | 	    context->yyYear = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 26: | case 26: | ||||||
| #line 352 "getdate.y" | #line 361 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyMonth = yyvsp[0].Number; | 	    context->yyMonth = yyvsp[0].Number; | ||||||
| 	    yyDay = yyvsp[-1].Number; | 	    context->yyDay = yyvsp[-1].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 27: | case 27: | ||||||
| #line 356 "getdate.y" | #line 365 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyMonth = yyvsp[-1].Number; | 	    context->yyMonth = yyvsp[-1].Number; | ||||||
| 	    yyDay = yyvsp[-2].Number; | 	    context->yyDay = yyvsp[-2].Number; | ||||||
| 	    yyYear = yyvsp[0].Number; | 	    context->yyYear = yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 28: | case 28: | ||||||
| #line 363 "getdate.y" | #line 372 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelSeconds = -yyRelSeconds; | 	    context->yyRelSeconds = -context->yyRelSeconds; | ||||||
| 	    yyRelMinutes = -yyRelMinutes; | 	    context->yyRelMinutes = -context->yyRelMinutes; | ||||||
| 	    yyRelHour = -yyRelHour; | 	    context->yyRelHour = -context->yyRelHour; | ||||||
| 	    yyRelDay = -yyRelDay; | 	    context->yyRelDay = -context->yyRelDay; | ||||||
| 	    yyRelMonth = -yyRelMonth; | 	    context->yyRelMonth = -context->yyRelMonth; | ||||||
| 	    yyRelYear = -yyRelYear; | 	    context->yyRelYear = -context->yyRelYear; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 30: | case 30: | ||||||
| #line 374 "getdate.y" | #line 383 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 31: | case 31: | ||||||
| #line 377 "getdate.y" | #line 386 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 32: | case 32: | ||||||
| #line 380 "getdate.y" | #line 389 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelYear += yyvsp[0].Number; | 	    context->yyRelYear += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 33: | case 33: | ||||||
| #line 383 "getdate.y" | #line 392 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 34: | case 34: | ||||||
| #line 386 "getdate.y" | #line 395 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 35: | case 35: | ||||||
| #line 389 "getdate.y" | #line 398 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMonth += yyvsp[0].Number; | 	    context->yyRelMonth += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 36: | case 36: | ||||||
| #line 392 "getdate.y" | #line 401 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 37: | case 37: | ||||||
| #line 395 "getdate.y" | #line 404 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 38: | case 38: | ||||||
| #line 398 "getdate.y" | #line 407 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelDay += yyvsp[0].Number; | 	    context->yyRelDay += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 39: | case 39: | ||||||
| #line 401 "getdate.y" | #line 410 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 40: | case 40: | ||||||
| #line 404 "getdate.y" | #line 413 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 41: | case 41: | ||||||
| #line 407 "getdate.y" | #line 416 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelHour += yyvsp[0].Number; | 	    context->yyRelHour += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 42: | case 42: | ||||||
| #line 410 "getdate.y" | #line 419 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 43: | case 43: | ||||||
| #line 413 "getdate.y" | #line 422 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 44: | case 44: | ||||||
| #line 416 "getdate.y" | #line 425 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelMinutes += yyvsp[0].Number; | 	    context->yyRelMinutes += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 45: | case 45: | ||||||
| #line 419 "getdate.y" | #line 428 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 46: | case 46: | ||||||
| #line 422 "getdate.y" | #line 431 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; | 	    context->yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 47: | case 47: | ||||||
| #line 425 "getdate.y" | #line 434 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyRelSeconds += yyvsp[0].Number; | 	    context->yyRelSeconds += yyvsp[0].Number; | ||||||
| 	; | 	; | ||||||
|     break;} |     break;} | ||||||
| case 48: | case 48: | ||||||
| #line 431 "getdate.y" | #line 440 "getdate.y" | ||||||
| { | { | ||||||
| 	    if (yyHaveTime && yyHaveDate && !yyHaveRel) | 	    if (context->yyHaveTime && context->yyHaveDate && | ||||||
| 	      yyYear = yyvsp[0].Number; | 		!context->yyHaveRel) | ||||||
|  | 	      context->yyYear = yyvsp[0].Number; | ||||||
| 	    else | 	    else | ||||||
| 	      { | 	      { | ||||||
| 		if (yyvsp[0].Number>10000) | 		if (yyvsp[0].Number>10000) | ||||||
| 		  { | 		  { | ||||||
| 		    yyHaveDate++; | 		    context->yyHaveDate++; | ||||||
| 		    yyDay= (yyvsp[0].Number)%100; | 		    context->yyDay= (yyvsp[0].Number)%100; | ||||||
| 		    yyMonth= (yyvsp[0].Number/100)%100; | 		    context->yyMonth= (yyvsp[0].Number/100)%100; | ||||||
| 		    yyYear = yyvsp[0].Number/10000; | 		    context->yyYear = yyvsp[0].Number/10000; | ||||||
| 		  } | 		  } | ||||||
| 		else | 		else | ||||||
| 		  { | 		  { | ||||||
| 		    yyHaveTime++; | 		    context->yyHaveTime++; | ||||||
| 		    if (yyvsp[0].Number < 100) | 		    if (yyvsp[0].Number < 100) | ||||||
| 		      { | 		      { | ||||||
| 			yyHour = yyvsp[0].Number; | 			context->yyHour = yyvsp[0].Number; | ||||||
| 			yyMinutes = 0; | 			context->yyMinutes = 0; | ||||||
| 		      } | 		      } | ||||||
| 		    else | 		    else | ||||||
| 		      { | 		      { | ||||||
| 		    	yyHour = yyvsp[0].Number / 100; | 		    	context->yyHour = yyvsp[0].Number / 100; | ||||||
| 		    	yyMinutes = yyvsp[0].Number % 100; | 		    	context->yyMinutes = yyvsp[0].Number % 100; | ||||||
| 		      } | 		      } | ||||||
| 		    yySeconds = 0; | 		    context->yySeconds = 0; | ||||||
| 		    yyMeridian = MER24; | 		    context->yyMeridian = MER24; | ||||||
| 		  } | 		  } | ||||||
| 	      } | 	      } | ||||||
| 	  ; | 	  ; | ||||||
|     break;} |     break;} | ||||||
| case 49: | case 49: | ||||||
| #line 464 "getdate.y" | #line 474 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyval.Meridian = MER24; | 	    yyval.Meridian = MER24; | ||||||
| 	  ; | 	  ; | ||||||
|     break;} |     break;} | ||||||
| case 50: | case 50: | ||||||
| #line 468 "getdate.y" | #line 478 "getdate.y" | ||||||
| { | { | ||||||
| 	    yyval.Meridian = yyvsp[0].Meridian; | 	    yyval.Meridian = yyvsp[0].Meridian; | ||||||
| 	  ; | 	  ; | ||||||
| @@ -1516,7 +1523,7 @@ yyerrhandle: | |||||||
|     } |     } | ||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
| #line 473 "getdate.y" | #line 483 "getdate.y" | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Include this file down here because bison inserts code above which | /* Include this file down here because bison inserts code above which | ||||||
| @@ -1772,7 +1779,8 @@ ToYear (Year) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| LookupWord (buff) | LookupWord (yylval, buff) | ||||||
|  |      YYSTYPE *yylval; | ||||||
|      char *buff; |      char *buff; | ||||||
| { | { | ||||||
|   register char *p; |   register char *p; | ||||||
| @@ -1788,12 +1796,12 @@ LookupWord (buff) | |||||||
|  |  | ||||||
|   if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) |   if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) | ||||||
|     { |     { | ||||||
|       yylval.Meridian = MERam; |       yylval->Meridian = MERam; | ||||||
|       return tMERIDIAN; |       return tMERIDIAN; | ||||||
|     } |     } | ||||||
|   if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) |   if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) | ||||||
|     { |     { | ||||||
|       yylval.Meridian = MERpm; |       yylval->Meridian = MERpm; | ||||||
|       return tMERIDIAN; |       return tMERIDIAN; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1814,13 +1822,13 @@ LookupWord (buff) | |||||||
| 	{ | 	{ | ||||||
| 	  if (strncmp (buff, tp->name, 3) == 0) | 	  if (strncmp (buff, tp->name, 3) == 0) | ||||||
| 	    { | 	    { | ||||||
| 	      yylval.Number = tp->value; | 	      yylval->Number = tp->value; | ||||||
| 	      return tp->type; | 	      return tp->type; | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|       else if (strcmp (buff, tp->name) == 0) |       else if (strcmp (buff, tp->name) == 0) | ||||||
| 	{ | 	{ | ||||||
| 	  yylval.Number = tp->value; | 	  yylval->Number = tp->value; | ||||||
| 	  return tp->type; | 	  return tp->type; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
| @@ -1828,7 +1836,7 @@ LookupWord (buff) | |||||||
|   for (tp = TimezoneTable; tp->name; tp++) |   for (tp = TimezoneTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1838,7 +1846,7 @@ LookupWord (buff) | |||||||
|   for (tp = UnitsTable; tp->name; tp++) |   for (tp = UnitsTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1850,7 +1858,7 @@ LookupWord (buff) | |||||||
|       for (tp = UnitsTable; tp->name; tp++) |       for (tp = UnitsTable; tp->name; tp++) | ||||||
| 	if (strcmp (buff, tp->name) == 0) | 	if (strcmp (buff, tp->name) == 0) | ||||||
| 	  { | 	  { | ||||||
| 	    yylval.Number = tp->value; | 	    yylval->Number = tp->value; | ||||||
| 	    return tp->type; | 	    return tp->type; | ||||||
| 	  } | 	  } | ||||||
|       buff[i] = 's';		/* Put back for "this" in OtherTable. */ |       buff[i] = 's';		/* Put back for "this" in OtherTable. */ | ||||||
| @@ -1859,7 +1867,7 @@ LookupWord (buff) | |||||||
|   for (tp = OtherTable; tp->name; tp++) |   for (tp = OtherTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -1869,7 +1877,7 @@ LookupWord (buff) | |||||||
|       for (tp = MilitaryTable; tp->name; tp++) |       for (tp = MilitaryTable; tp->name; tp++) | ||||||
| 	if (strcmp (buff, tp->name) == 0) | 	if (strcmp (buff, tp->name) == 0) | ||||||
| 	  { | 	  { | ||||||
| 	    yylval.Number = tp->value; | 	    yylval->Number = tp->value; | ||||||
| 	    return tp->type; | 	    return tp->type; | ||||||
| 	  } | 	  } | ||||||
|     } |     } | ||||||
| @@ -1885,7 +1893,7 @@ LookupWord (buff) | |||||||
|     for (tp = TimezoneTable; tp->name; tp++) |     for (tp = TimezoneTable; tp->name; tp++) | ||||||
|       if (strcmp (buff, tp->name) == 0) |       if (strcmp (buff, tp->name) == 0) | ||||||
| 	{ | 	{ | ||||||
| 	  yylval.Number = tp->value; | 	  yylval->Number = tp->value; | ||||||
| 	  return tp->type; | 	  return tp->type; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1893,7 +1901,9 @@ LookupWord (buff) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| yylex () | yylex (yylval, cookie) | ||||||
|  |      YYSTYPE *yylval; | ||||||
|  |      void *cookie; | ||||||
| { | { | ||||||
|   register unsigned char c; |   register unsigned char c; | ||||||
|   register char *p; |   register char *p; | ||||||
| @@ -1903,42 +1913,42 @@ yylex () | |||||||
|  |  | ||||||
|   for (;;) |   for (;;) | ||||||
|     { |     { | ||||||
|       while (ISSPACE ((unsigned char) *yyInput)) |       while (ISSPACE ((unsigned char) *context->yyInput)) | ||||||
| 	yyInput++; | 	context->yyInput++; | ||||||
|  |  | ||||||
|       if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') |       if (ISDIGIT (c = *context->yyInput) || c == '-' || c == '+') | ||||||
| 	{ | 	{ | ||||||
| 	  if (c == '-' || c == '+') | 	  if (c == '-' || c == '+') | ||||||
| 	    { | 	    { | ||||||
| 	      sign = c == '-' ? -1 : 1; | 	      sign = c == '-' ? -1 : 1; | ||||||
| 	      if (!ISDIGIT (*++yyInput)) | 	      if (!ISDIGIT (*++context->yyInput)) | ||||||
| 		/* skip the '-' sign */ | 		/* skip the '-' sign */ | ||||||
| 		continue; | 		continue; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    sign = 0; | 	    sign = 0; | ||||||
| 	  for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) | 	  for (yylval->Number = 0; ISDIGIT (c = *context->yyInput++);) | ||||||
| 	    yylval.Number = 10 * yylval.Number + c - '0'; | 	    yylval->Number = 10 * yylval->Number + c - '0'; | ||||||
| 	  yyInput--; | 	  context->yyInput--; | ||||||
| 	  if (sign < 0) | 	  if (sign < 0) | ||||||
| 	    yylval.Number = -yylval.Number; | 	    yylval->Number = -yylval->Number; | ||||||
| 	  return sign ? tSNUMBER : tUNUMBER; | 	  return sign ? tSNUMBER : tUNUMBER; | ||||||
| 	} | 	} | ||||||
|       if (ISALPHA (c)) |       if (ISALPHA (c)) | ||||||
| 	{ | 	{ | ||||||
| 	  for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) | 	  for (p = buff; (c = *context->yyInput++, ISALPHA (c)) || c == '.';) | ||||||
| 	    if (p < &buff[sizeof buff - 1]) | 	    if (p < &buff[sizeof buff - 1]) | ||||||
| 	      *p++ = c; | 	      *p++ = c; | ||||||
| 	  *p = '\0'; | 	  *p = '\0'; | ||||||
| 	  yyInput--; | 	  context->yyInput--; | ||||||
| 	  return LookupWord (buff); | 	  return LookupWord (yylval, buff); | ||||||
| 	} | 	} | ||||||
|       if (c != '(') |       if (c != '(') | ||||||
| 	return *yyInput++; | 	return *context->yyInput++; | ||||||
|       Count = 0; |       Count = 0; | ||||||
|       do |       do | ||||||
| 	{ | 	{ | ||||||
| 	  c = *yyInput++; | 	  c = *context->yyInput++; | ||||||
| 	  if (c == '\0') | 	  if (c == '\0') | ||||||
| 	    return c; | 	    return c; | ||||||
| 	  if (c == '(') | 	  if (c == '(') | ||||||
| @@ -1978,10 +1988,11 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| { | { | ||||||
|   struct tm tm, tm0, *tmp; |   struct tm tm, tm0, *tmp; | ||||||
|   time_t Start; |   time_t Start; | ||||||
|  |   CONTEXT cookie; | ||||||
| #ifdef HAVE_LOCALTIME_R | #ifdef HAVE_LOCALTIME_R | ||||||
|   struct tm keeptime; |   struct tm keeptime; | ||||||
| #endif | #endif | ||||||
|   yyInput = p; |   cookie.yyInput = p; | ||||||
|   Start = now ? *now : time ((time_t *) NULL); |   Start = now ? *now : time ((time_t *) NULL); | ||||||
| #ifdef HAVE_LOCALTIME_R | #ifdef HAVE_LOCALTIME_R | ||||||
|   tmp = (struct tm *)localtime_r(&Start, &keeptime); |   tmp = (struct tm *)localtime_r(&Start, &keeptime); | ||||||
| @@ -1990,52 +2001,55 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| #endif | #endif | ||||||
|   if (!tmp) |   if (!tmp) | ||||||
|     return -1; |     return -1; | ||||||
|   yyYear = tmp->tm_year + TM_YEAR_ORIGIN; |   cookie.yyYear = tmp->tm_year + TM_YEAR_ORIGIN; | ||||||
|   yyMonth = tmp->tm_mon + 1; |   cookie.yyMonth = tmp->tm_mon + 1; | ||||||
|   yyDay = tmp->tm_mday; |   cookie.yyDay = tmp->tm_mday; | ||||||
|   yyHour = tmp->tm_hour; |   cookie.yyHour = tmp->tm_hour; | ||||||
|   yyMinutes = tmp->tm_min; |   cookie.yyMinutes = tmp->tm_min; | ||||||
|   yySeconds = tmp->tm_sec; |   cookie.yySeconds = tmp->tm_sec; | ||||||
|   tm.tm_isdst = tmp->tm_isdst; |   tm.tm_isdst = tmp->tm_isdst; | ||||||
|   yyMeridian = MER24; |   cookie.yyMeridian = MER24; | ||||||
|   yyRelSeconds = 0; |   cookie.yyRelSeconds = 0; | ||||||
|   yyRelMinutes = 0; |   cookie.yyRelMinutes = 0; | ||||||
|   yyRelHour = 0; |   cookie.yyRelHour = 0; | ||||||
|   yyRelDay = 0; |   cookie.yyRelDay = 0; | ||||||
|   yyRelMonth = 0; |   cookie.yyRelMonth = 0; | ||||||
|   yyRelYear = 0; |   cookie.yyRelYear = 0; | ||||||
|   yyHaveDate = 0; |   cookie.yyHaveDate = 0; | ||||||
|   yyHaveDay = 0; |   cookie.yyHaveDay = 0; | ||||||
|   yyHaveRel = 0; |   cookie.yyHaveRel = 0; | ||||||
|   yyHaveTime = 0; |   cookie.yyHaveTime = 0; | ||||||
|   yyHaveZone = 0; |   cookie.yyHaveZone = 0; | ||||||
|  |  | ||||||
|   if (yyparse () |   if (yyparse (&cookie) | ||||||
|       || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) |       || cookie.yyHaveTime > 1 || cookie.yyHaveZone > 1 || | ||||||
|  |       cookie.yyHaveDate > 1 || cookie.yyHaveDay > 1) | ||||||
|     return -1; |     return -1; | ||||||
|  |  | ||||||
|   tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; |   tm.tm_year = ToYear (cookie.yyYear) - TM_YEAR_ORIGIN + cookie.yyRelYear; | ||||||
|   tm.tm_mon = yyMonth - 1 + yyRelMonth; |   tm.tm_mon = cookie.yyMonth - 1 + cookie.yyRelMonth; | ||||||
|   tm.tm_mday = yyDay + yyRelDay; |   tm.tm_mday = cookie.yyDay + cookie.yyRelDay; | ||||||
|   if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) |   if (cookie.yyHaveTime || | ||||||
|  |       (cookie.yyHaveRel && !cookie.yyHaveDate && !cookie.yyHaveDay)) | ||||||
|     { |     { | ||||||
|       tm.tm_hour = ToHour (yyHour, yyMeridian); |       tm.tm_hour = ToHour (cookie.yyHour, cookie.yyMeridian); | ||||||
|       if (tm.tm_hour < 0) |       if (tm.tm_hour < 0) | ||||||
| 	return -1; | 	return -1; | ||||||
|       tm.tm_min = yyMinutes; |       tm.tm_min = cookie.yyMinutes; | ||||||
|       tm.tm_sec = yySeconds; |       tm.tm_sec = cookie.yySeconds; | ||||||
|     } |     } | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       tm.tm_hour = tm.tm_min = tm.tm_sec = 0; |       tm.tm_hour = tm.tm_min = tm.tm_sec = 0; | ||||||
|     } |     } | ||||||
|   tm.tm_hour += yyRelHour; |   tm.tm_hour += cookie.yyRelHour; | ||||||
|   tm.tm_min += yyRelMinutes; |   tm.tm_min += cookie.yyRelMinutes; | ||||||
|   tm.tm_sec += yyRelSeconds; |   tm.tm_sec += cookie.yyRelSeconds; | ||||||
|  |  | ||||||
|   /* Let mktime deduce tm_isdst if we have an absolute timestamp, |   /* Let mktime deduce tm_isdst if we have an absolute timestamp, | ||||||
|      or if the relative timestamp mentions days, months, or years.  */ |      or if the relative timestamp mentions days, months, or years.  */ | ||||||
|   if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear) |   if (cookie.yyHaveDate | cookie.yyHaveDay | cookie.yyHaveTime | | ||||||
|  |       cookie.yyRelDay | cookie.yyRelMonth | cookie.yyRelYear) | ||||||
|     tm.tm_isdst = -1; |     tm.tm_isdst = -1; | ||||||
|  |  | ||||||
|   tm0 = tm; |   tm0 = tm; | ||||||
| @@ -2053,18 +2067,18 @@ curl_getdate (const char *p, const time_t *now) | |||||||
|          we apply mktime to 1970-01-02 08:00:00 instead and adjust the time |          we apply mktime to 1970-01-02 08:00:00 instead and adjust the time | ||||||
|          zone by 24 hours to compensate.  This algorithm assumes that |          zone by 24 hours to compensate.  This algorithm assumes that | ||||||
|          there is no DST transition within a day of the time_t boundaries.  */ |          there is no DST transition within a day of the time_t boundaries.  */ | ||||||
|       if (yyHaveZone) |       if (cookie.yyHaveZone) | ||||||
| 	{ | 	{ | ||||||
| 	  tm = tm0; | 	  tm = tm0; | ||||||
| 	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) | 	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) | ||||||
| 	    { | 	    { | ||||||
| 	      tm.tm_mday++; | 	      tm.tm_mday++; | ||||||
| 	      yyTimezone -= 24 * 60; | 	      cookie.yyTimezone -= 24 * 60; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
| 	      tm.tm_mday--; | 	      tm.tm_mday--; | ||||||
| 	      yyTimezone += 24 * 60; | 	      cookie.yyTimezone += 24 * 60; | ||||||
| 	    } | 	    } | ||||||
| 	  Start = mktime (&tm); | 	  Start = mktime (&tm); | ||||||
| 	} | 	} | ||||||
| @@ -2073,22 +2087,29 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| 	return Start; | 	return Start; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (yyHaveDay && !yyHaveDate) |   if (cookie.yyHaveDay && !cookie.yyHaveDate) | ||||||
|     { |     { | ||||||
|       tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 |       tm.tm_mday += ((cookie.yyDayNumber - tm.tm_wday + 7) % 7 | ||||||
| 		     + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); | 		     + 7 * (cookie.yyDayOrdinal - (0 < cookie.yyDayOrdinal))); | ||||||
|       Start = mktime (&tm); |       Start = mktime (&tm); | ||||||
|       if (Start == (time_t) -1) |       if (Start == (time_t) -1) | ||||||
| 	return Start; | 	return Start; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (yyHaveZone) |   if (cookie.yyHaveZone) | ||||||
|     { |     { | ||||||
|       long delta; |       long delta; | ||||||
|       struct tm *gmt = gmtime (&Start); |       struct tm *gmt; | ||||||
|  | #ifdef HAVE_GMTIME_R | ||||||
|  |       /* thread-safe version */ | ||||||
|  |       struct tm keeptime; | ||||||
|  |       gmt = (struct tm *)gmtime_r(&Start, &keeptime); | ||||||
|  | #else | ||||||
|  |       gmt = gmtime(&Start); | ||||||
|  | #endif | ||||||
|       if (!gmt) |       if (!gmt) | ||||||
| 	return -1; | 	return -1; | ||||||
|       delta = yyTimezone * 60L + difftm (&tm, gmt); |       delta = cookie.yyTimezone * 60L + difftm (&tm, gmt); | ||||||
|       if ((Start + delta < Start) != (delta < 0)) |       if ((Start + delta < Start) != (delta < 0)) | ||||||
| 	return -1;		/* time_t overflow */ | 	return -1;		/* time_t overflow */ | ||||||
|       Start += delta; |       Start += delta; | ||||||
| @@ -2126,11 +2147,3 @@ main (ac, av) | |||||||
|   /* NOTREACHED */ |   /* NOTREACHED */ | ||||||
| } | } | ||||||
| #endif /* defined (TEST) */ | #endif /* defined (TEST) */ | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * local variables: |  | ||||||
|  * eval: (load-file "../curl-mode.el") |  | ||||||
|  * end: |  | ||||||
|  * vim600: fdm=marker |  | ||||||
|  * vim: et sw=2 ts=2 sts=2 tw=78 |  | ||||||
|  */ |  | ||||||
|   | |||||||
| @@ -7,9 +7,7 @@ | |||||||
| **  This code is in the public domain and has no copyright. | **  This code is in the public domain and has no copyright. | ||||||
| */ | */ | ||||||
|  |  | ||||||
| #if HAVE_CONFIG_H | # include "setup.h" | ||||||
| # include <config.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef PARAMS | #ifndef PARAMS | ||||||
| # if defined PROTOTYPES || (defined __STDC__ && __STDC__) | # if defined PROTOTYPES || (defined __STDC__ && __STDC__) | ||||||
|   | |||||||
							
								
								
									
										412
									
								
								lib/getdate.y
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								lib/getdate.y
									
									
									
									
									
								
							| @@ -10,8 +10,6 @@ | |||||||
|  |  | ||||||
| #include "setup.h" | #include "setup.h" | ||||||
|  |  | ||||||
| #ifdef HAVE_CONFIG_H |  | ||||||
| # include "config.h" |  | ||||||
| # ifdef HAVE_ALLOCA_H | # ifdef HAVE_ALLOCA_H | ||||||
| #  include <alloca.h> | #  include <alloca.h> | ||||||
| # endif | # endif | ||||||
| @@ -19,6 +17,10 @@ | |||||||
| # ifdef HAVE_TIME_H | # ifdef HAVE_TIME_H | ||||||
| #  include <time.h> | #  include <time.h> | ||||||
| # endif | # endif | ||||||
|  |  | ||||||
|  | #ifndef YYDEBUG | ||||||
|  |   /* to satisfy gcc -Wundef, we set this to 0 */ | ||||||
|  | #define YYDEBUG 0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Since the code of getdate.y is not included in the Emacs executable | /* Since the code of getdate.y is not included in the Emacs executable | ||||||
| @@ -168,41 +170,48 @@ typedef enum _MERIDIAN { | |||||||
|     MERam, MERpm, MER24 |     MERam, MERpm, MER24 | ||||||
| } MERIDIAN; | } MERIDIAN; | ||||||
|  |  | ||||||
|  | /* parse results and input string */ | ||||||
|  | typedef struct _CONTEXT { | ||||||
|  |     const char	*yyInput; | ||||||
|  |     int		yyDayOrdinal; | ||||||
|  |     int		yyDayNumber; | ||||||
|  |     int		yyHaveDate; | ||||||
|  |     int		yyHaveDay; | ||||||
|  |     int		yyHaveRel; | ||||||
|  |     int		yyHaveTime; | ||||||
|  |     int		yyHaveZone; | ||||||
|  |     int		yyTimezone; | ||||||
|  |     int		yyDay; | ||||||
|  |     int		yyHour; | ||||||
|  |     int		yyMinutes; | ||||||
|  |     int		yyMonth; | ||||||
|  |     int		yySeconds; | ||||||
|  |     int		yyYear; | ||||||
|  |     MERIDIAN	yyMeridian; | ||||||
|  |     int		yyRelDay; | ||||||
|  |     int		yyRelHour; | ||||||
|  |     int		yyRelMinutes; | ||||||
|  |     int		yyRelMonth; | ||||||
|  |     int		yyRelSeconds; | ||||||
|  |     int		yyRelYear; | ||||||
|  | } CONTEXT; | ||||||
|  |  | ||||||
| /* | /* enable use of extra argument to yyparse and yylex which can be used to pass | ||||||
| **  Global variables.  We could get rid of most of these by using a good | **  in a user defined value (CONTEXT struct in our case) | ||||||
| **  union as the yacc stack.  (This routine was originally written before |  | ||||||
| **  yacc had the %union construct.)  Maybe someday; right now we only use |  | ||||||
| **  the %union very rarely. |  | ||||||
| */ | */ | ||||||
| static const char	*yyInput; | #define YYPARSE_PARAM cookie | ||||||
| static int	yyDayOrdinal; | #define YYLEX_PARAM cookie | ||||||
| static int	yyDayNumber; | #define context ((CONTEXT *) cookie) | ||||||
| static int	yyHaveDate; |  | ||||||
| static int	yyHaveDay; |  | ||||||
| static int	yyHaveRel; |  | ||||||
| static int	yyHaveTime; |  | ||||||
| static int	yyHaveZone; |  | ||||||
| static int	yyTimezone; |  | ||||||
| static int	yyDay; |  | ||||||
| static int	yyHour; |  | ||||||
| static int	yyMinutes; |  | ||||||
| static int	yyMonth; |  | ||||||
| static int	yySeconds; |  | ||||||
| static int	yyYear; |  | ||||||
| static MERIDIAN	yyMeridian; |  | ||||||
| static int	yyRelDay; |  | ||||||
| static int	yyRelHour; |  | ||||||
| static int	yyRelMinutes; |  | ||||||
| static int	yyRelMonth; |  | ||||||
| static int	yyRelSeconds; |  | ||||||
| static int	yyRelYear; |  | ||||||
|  |  | ||||||
| %} | %} | ||||||
|  |  | ||||||
| /* This grammar has 13 shift/reduce conflicts. */ | /* This grammar has 13 shift/reduce conflicts. */ | ||||||
| %expect 13 | %expect 13 | ||||||
|  |  | ||||||
|  | /* turn global variables into locals, additionally enable extra arguments | ||||||
|  | ** for yylex (pointer to yylval and user defined value) | ||||||
|  | */ | ||||||
|  | %pure_parser | ||||||
|  |  | ||||||
| %union { | %union { | ||||||
|     int			Number; |     int			Number; | ||||||
|     enum _MERIDIAN	Meridian; |     enum _MERIDIAN	Meridian; | ||||||
| @@ -224,91 +233,91 @@ spec	: /* NULL */ | |||||||
| 	; | 	; | ||||||
|  |  | ||||||
| item	: time { | item	: time { | ||||||
| 	    yyHaveTime++; | 	    context->yyHaveTime++; | ||||||
| 	} | 	} | ||||||
| 	| zone { | 	| zone { | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	} | 	} | ||||||
| 	| date { | 	| date { | ||||||
| 	    yyHaveDate++; | 	    context->yyHaveDate++; | ||||||
| 	} | 	} | ||||||
| 	| day { | 	| day { | ||||||
| 	    yyHaveDay++; | 	    context->yyHaveDay++; | ||||||
| 	} | 	} | ||||||
| 	| rel { | 	| rel { | ||||||
| 	    yyHaveRel++; | 	    context->yyHaveRel++; | ||||||
| 	} | 	} | ||||||
| 	| number | 	| number | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| time	: tUNUMBER tMERIDIAN { | time	: tUNUMBER tMERIDIAN { | ||||||
| 	    yyHour = $1; | 	    context->yyHour = $1; | ||||||
| 	    yyMinutes = 0; | 	    context->yyMinutes = 0; | ||||||
| 	    yySeconds = 0; | 	    context->yySeconds = 0; | ||||||
| 	    yyMeridian = $2; | 	    context->yyMeridian = $2; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER ':' tUNUMBER o_merid { | 	| tUNUMBER ':' tUNUMBER o_merid { | ||||||
| 	    yyHour = $1; | 	    context->yyHour = $1; | ||||||
| 	    yyMinutes = $3; | 	    context->yyMinutes = $3; | ||||||
| 	    yySeconds = 0; | 	    context->yySeconds = 0; | ||||||
| 	    yyMeridian = $4; | 	    context->yyMeridian = $4; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER ':' tUNUMBER tSNUMBER { | 	| tUNUMBER ':' tUNUMBER tSNUMBER { | ||||||
| 	    yyHour = $1; | 	    context->yyHour = $1; | ||||||
| 	    yyMinutes = $3; | 	    context->yyMinutes = $3; | ||||||
| 	    yyMeridian = MER24; | 	    context->yyMeridian = MER24; | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	    yyTimezone = ($4 < 0 | 	    context->yyTimezone = ($4 < 0 | ||||||
| 				   ? -$4 % 100 + (-$4 / 100) * 60 | 				   ? -$4 % 100 + (-$4 / 100) * 60 | ||||||
| 				   : - ($4 % 100 + ($4 / 100) * 60)); | 				   : - ($4 % 100 + ($4 / 100) * 60)); | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { | 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { | ||||||
| 	    yyHour = $1; | 	    context->yyHour = $1; | ||||||
| 	    yyMinutes = $3; | 	    context->yyMinutes = $3; | ||||||
| 	    yySeconds = $5; | 	    context->yySeconds = $5; | ||||||
| 	    yyMeridian = $6; | 	    context->yyMeridian = $6; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { | 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { | ||||||
| 	    yyHour = $1; | 	    context->yyHour = $1; | ||||||
| 	    yyMinutes = $3; | 	    context->yyMinutes = $3; | ||||||
| 	    yySeconds = $5; | 	    context->yySeconds = $5; | ||||||
| 	    yyMeridian = MER24; | 	    context->yyMeridian = MER24; | ||||||
| 	    yyHaveZone++; | 	    context->yyHaveZone++; | ||||||
| 	    yyTimezone = ($6 < 0 | 	    context->yyTimezone = ($6 < 0 | ||||||
| 				   ? -$6 % 100 + (-$6 / 100) * 60 | 				   ? -$6 % 100 + (-$6 / 100) * 60 | ||||||
| 				   : - ($6 % 100 + ($6 / 100) * 60)); | 				   : - ($6 % 100 + ($6 / 100) * 60)); | ||||||
| 	} | 	} | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| zone	: tZONE { | zone	: tZONE { | ||||||
| 	    yyTimezone = $1; | 	    context->yyTimezone = $1; | ||||||
| 	} | 	} | ||||||
| 	| tDAYZONE { | 	| tDAYZONE { | ||||||
| 	    yyTimezone = $1 - 60; | 	    context->yyTimezone = $1 - 60; | ||||||
| 	} | 	} | ||||||
| 	| | 	| | ||||||
| 	  tZONE tDST { | 	  tZONE tDST { | ||||||
| 	    yyTimezone = $1 - 60; | 	    context->yyTimezone = $1 - 60; | ||||||
| 	} | 	} | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| day	: tDAY { | day	: tDAY { | ||||||
| 	    yyDayOrdinal = 1; | 	    context->yyDayOrdinal = 1; | ||||||
| 	    yyDayNumber = $1; | 	    context->yyDayNumber = $1; | ||||||
| 	} | 	} | ||||||
| 	| tDAY ',' { | 	| tDAY ',' { | ||||||
| 	    yyDayOrdinal = 1; | 	    context->yyDayOrdinal = 1; | ||||||
| 	    yyDayNumber = $1; | 	    context->yyDayNumber = $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tDAY { | 	| tUNUMBER tDAY { | ||||||
| 	    yyDayOrdinal = $1; | 	    context->yyDayOrdinal = $1; | ||||||
| 	    yyDayNumber = $2; | 	    context->yyDayNumber = $2; | ||||||
| 	} | 	} | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| date	: tUNUMBER '/' tUNUMBER { | date	: tUNUMBER '/' tUNUMBER { | ||||||
| 	    yyMonth = $1; | 	    context->yyMonth = $1; | ||||||
| 	    yyDay = $3; | 	    context->yyDay = $3; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER '/' tUNUMBER '/' tUNUMBER { | 	| tUNUMBER '/' tUNUMBER '/' tUNUMBER { | ||||||
| 	  /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. | 	  /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. | ||||||
| @@ -317,144 +326,145 @@ date	: tUNUMBER '/' tUNUMBER { | |||||||
| 	     you want portability, use the ISO 8601 format.  */ | 	     you want portability, use the ISO 8601 format.  */ | ||||||
| 	  if ($1 >= 1000) | 	  if ($1 >= 1000) | ||||||
| 	    { | 	    { | ||||||
| 	      yyYear = $1; | 	      context->yyYear = $1; | ||||||
| 	      yyMonth = $3; | 	      context->yyMonth = $3; | ||||||
| 	      yyDay = $5; | 	      context->yyDay = $5; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
| 	      yyMonth = $1; | 	      context->yyMonth = $1; | ||||||
| 	      yyDay = $3; | 	      context->yyDay = $3; | ||||||
| 	      yyYear = $5; | 	      context->yyYear = $5; | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tSNUMBER tSNUMBER { | 	| tUNUMBER tSNUMBER tSNUMBER { | ||||||
| 	    /* ISO 8601 format.  yyyy-mm-dd.  */ | 	    /* ISO 8601 format.  yyyy-mm-dd.  */ | ||||||
| 	    yyYear = $1; | 	    context->yyYear = $1; | ||||||
| 	    yyMonth = -$2; | 	    context->yyMonth = -$2; | ||||||
| 	    yyDay = -$3; | 	    context->yyDay = -$3; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tMONTH tSNUMBER { | 	| tUNUMBER tMONTH tSNUMBER { | ||||||
| 	    /* e.g. 17-JUN-1992.  */ | 	    /* e.g. 17-JUN-1992.  */ | ||||||
| 	    yyDay = $1; | 	    context->yyDay = $1; | ||||||
| 	    yyMonth = $2; | 	    context->yyMonth = $2; | ||||||
| 	    yyYear = -$3; | 	    context->yyYear = -$3; | ||||||
| 	} | 	} | ||||||
| 	| tMONTH tUNUMBER { | 	| tMONTH tUNUMBER { | ||||||
| 	    yyMonth = $1; | 	    context->yyMonth = $1; | ||||||
| 	    yyDay = $2; | 	    context->yyDay = $2; | ||||||
| 	} | 	} | ||||||
| 	| tMONTH tUNUMBER ',' tUNUMBER { | 	| tMONTH tUNUMBER ',' tUNUMBER { | ||||||
| 	    yyMonth = $1; | 	    context->yyMonth = $1; | ||||||
| 	    yyDay = $2; | 	    context->yyDay = $2; | ||||||
| 	    yyYear = $4; | 	    context->yyYear = $4; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tMONTH { | 	| tUNUMBER tMONTH { | ||||||
| 	    yyMonth = $2; | 	    context->yyMonth = $2; | ||||||
| 	    yyDay = $1; | 	    context->yyDay = $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tMONTH tUNUMBER { | 	| tUNUMBER tMONTH tUNUMBER { | ||||||
| 	    yyMonth = $2; | 	    context->yyMonth = $2; | ||||||
| 	    yyDay = $1; | 	    context->yyDay = $1; | ||||||
| 	    yyYear = $3; | 	    context->yyYear = $3; | ||||||
| 	} | 	} | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| rel	: relunit tAGO { | rel	: relunit tAGO { | ||||||
| 	    yyRelSeconds = -yyRelSeconds; | 	    context->yyRelSeconds = -context->yyRelSeconds; | ||||||
| 	    yyRelMinutes = -yyRelMinutes; | 	    context->yyRelMinutes = -context->yyRelMinutes; | ||||||
| 	    yyRelHour = -yyRelHour; | 	    context->yyRelHour = -context->yyRelHour; | ||||||
| 	    yyRelDay = -yyRelDay; | 	    context->yyRelDay = -context->yyRelDay; | ||||||
| 	    yyRelMonth = -yyRelMonth; | 	    context->yyRelMonth = -context->yyRelMonth; | ||||||
| 	    yyRelYear = -yyRelYear; | 	    context->yyRelYear = -context->yyRelYear; | ||||||
| 	} | 	} | ||||||
| 	| relunit | 	| relunit | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| relunit	: tUNUMBER tYEAR_UNIT { | relunit	: tUNUMBER tYEAR_UNIT { | ||||||
| 	    yyRelYear += $1 * $2; | 	    context->yyRelYear += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tYEAR_UNIT { | 	| tSNUMBER tYEAR_UNIT { | ||||||
| 	    yyRelYear += $1 * $2; | 	    context->yyRelYear += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tYEAR_UNIT { | 	| tYEAR_UNIT { | ||||||
| 	    yyRelYear += $1; | 	    context->yyRelYear += $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tMONTH_UNIT { | 	| tUNUMBER tMONTH_UNIT { | ||||||
| 	    yyRelMonth += $1 * $2; | 	    context->yyRelMonth += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tMONTH_UNIT { | 	| tSNUMBER tMONTH_UNIT { | ||||||
| 	    yyRelMonth += $1 * $2; | 	    context->yyRelMonth += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tMONTH_UNIT { | 	| tMONTH_UNIT { | ||||||
| 	    yyRelMonth += $1; | 	    context->yyRelMonth += $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tDAY_UNIT { | 	| tUNUMBER tDAY_UNIT { | ||||||
| 	    yyRelDay += $1 * $2; | 	    context->yyRelDay += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tDAY_UNIT { | 	| tSNUMBER tDAY_UNIT { | ||||||
| 	    yyRelDay += $1 * $2; | 	    context->yyRelDay += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tDAY_UNIT { | 	| tDAY_UNIT { | ||||||
| 	    yyRelDay += $1; | 	    context->yyRelDay += $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tHOUR_UNIT { | 	| tUNUMBER tHOUR_UNIT { | ||||||
| 	    yyRelHour += $1 * $2; | 	    context->yyRelHour += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tHOUR_UNIT { | 	| tSNUMBER tHOUR_UNIT { | ||||||
| 	    yyRelHour += $1 * $2; | 	    context->yyRelHour += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tHOUR_UNIT { | 	| tHOUR_UNIT { | ||||||
| 	    yyRelHour += $1; | 	    context->yyRelHour += $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tMINUTE_UNIT { | 	| tUNUMBER tMINUTE_UNIT { | ||||||
| 	    yyRelMinutes += $1 * $2; | 	    context->yyRelMinutes += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tMINUTE_UNIT { | 	| tSNUMBER tMINUTE_UNIT { | ||||||
| 	    yyRelMinutes += $1 * $2; | 	    context->yyRelMinutes += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tMINUTE_UNIT { | 	| tMINUTE_UNIT { | ||||||
| 	    yyRelMinutes += $1; | 	    context->yyRelMinutes += $1; | ||||||
| 	} | 	} | ||||||
| 	| tUNUMBER tSEC_UNIT { | 	| tUNUMBER tSEC_UNIT { | ||||||
| 	    yyRelSeconds += $1 * $2; | 	    context->yyRelSeconds += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSNUMBER tSEC_UNIT { | 	| tSNUMBER tSEC_UNIT { | ||||||
| 	    yyRelSeconds += $1 * $2; | 	    context->yyRelSeconds += $1 * $2; | ||||||
| 	} | 	} | ||||||
| 	| tSEC_UNIT { | 	| tSEC_UNIT { | ||||||
| 	    yyRelSeconds += $1; | 	    context->yyRelSeconds += $1; | ||||||
| 	} | 	} | ||||||
| 	; | 	; | ||||||
|  |  | ||||||
| number	: tUNUMBER | number	: tUNUMBER | ||||||
|           { |           { | ||||||
| 	    if (yyHaveTime && yyHaveDate && !yyHaveRel) | 	    if (context->yyHaveTime && context->yyHaveDate && | ||||||
| 	      yyYear = $1; | 		!context->yyHaveRel) | ||||||
|  | 	      context->yyYear = $1; | ||||||
| 	    else | 	    else | ||||||
| 	      { | 	      { | ||||||
| 		if ($1>10000) | 		if ($1>10000) | ||||||
| 		  { | 		  { | ||||||
| 		    yyHaveDate++; | 		    context->yyHaveDate++; | ||||||
| 		    yyDay= ($1)%100; | 		    context->yyDay= ($1)%100; | ||||||
| 		    yyMonth= ($1/100)%100; | 		    context->yyMonth= ($1/100)%100; | ||||||
| 		    yyYear = $1/10000; | 		    context->yyYear = $1/10000; | ||||||
| 		  } | 		  } | ||||||
| 		else | 		else | ||||||
| 		  { | 		  { | ||||||
| 		    yyHaveTime++; | 		    context->yyHaveTime++; | ||||||
| 		    if ($1 < 100) | 		    if ($1 < 100) | ||||||
| 		      { | 		      { | ||||||
| 			yyHour = $1; | 			context->yyHour = $1; | ||||||
| 			yyMinutes = 0; | 			context->yyMinutes = 0; | ||||||
| 		      } | 		      } | ||||||
| 		    else | 		    else | ||||||
| 		      { | 		      { | ||||||
| 		    	yyHour = $1 / 100; | 		    	context->yyHour = $1 / 100; | ||||||
| 		    	yyMinutes = $1 % 100; | 		    	context->yyMinutes = $1 % 100; | ||||||
| 		      } | 		      } | ||||||
| 		    yySeconds = 0; | 		    context->yySeconds = 0; | ||||||
| 		    yyMeridian = MER24; | 		    context->yyMeridian = MER24; | ||||||
| 		  } | 		  } | ||||||
| 	      } | 	      } | ||||||
| 	  } | 	  } | ||||||
| @@ -725,7 +735,8 @@ ToYear (Year) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| LookupWord (buff) | LookupWord (yylval, buff) | ||||||
|  |      YYSTYPE *yylval; | ||||||
|      char *buff; |      char *buff; | ||||||
| { | { | ||||||
|   register char *p; |   register char *p; | ||||||
| @@ -741,12 +752,12 @@ LookupWord (buff) | |||||||
|  |  | ||||||
|   if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) |   if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) | ||||||
|     { |     { | ||||||
|       yylval.Meridian = MERam; |       yylval->Meridian = MERam; | ||||||
|       return tMERIDIAN; |       return tMERIDIAN; | ||||||
|     } |     } | ||||||
|   if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) |   if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) | ||||||
|     { |     { | ||||||
|       yylval.Meridian = MERpm; |       yylval->Meridian = MERpm; | ||||||
|       return tMERIDIAN; |       return tMERIDIAN; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -767,13 +778,13 @@ LookupWord (buff) | |||||||
| 	{ | 	{ | ||||||
| 	  if (strncmp (buff, tp->name, 3) == 0) | 	  if (strncmp (buff, tp->name, 3) == 0) | ||||||
| 	    { | 	    { | ||||||
| 	      yylval.Number = tp->value; | 	      yylval->Number = tp->value; | ||||||
| 	      return tp->type; | 	      return tp->type; | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|       else if (strcmp (buff, tp->name) == 0) |       else if (strcmp (buff, tp->name) == 0) | ||||||
| 	{ | 	{ | ||||||
| 	  yylval.Number = tp->value; | 	  yylval->Number = tp->value; | ||||||
| 	  return tp->type; | 	  return tp->type; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
| @@ -781,7 +792,7 @@ LookupWord (buff) | |||||||
|   for (tp = TimezoneTable; tp->name; tp++) |   for (tp = TimezoneTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -791,7 +802,7 @@ LookupWord (buff) | |||||||
|   for (tp = UnitsTable; tp->name; tp++) |   for (tp = UnitsTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -803,7 +814,7 @@ LookupWord (buff) | |||||||
|       for (tp = UnitsTable; tp->name; tp++) |       for (tp = UnitsTable; tp->name; tp++) | ||||||
| 	if (strcmp (buff, tp->name) == 0) | 	if (strcmp (buff, tp->name) == 0) | ||||||
| 	  { | 	  { | ||||||
| 	    yylval.Number = tp->value; | 	    yylval->Number = tp->value; | ||||||
| 	    return tp->type; | 	    return tp->type; | ||||||
| 	  } | 	  } | ||||||
|       buff[i] = 's';		/* Put back for "this" in OtherTable. */ |       buff[i] = 's';		/* Put back for "this" in OtherTable. */ | ||||||
| @@ -812,7 +823,7 @@ LookupWord (buff) | |||||||
|   for (tp = OtherTable; tp->name; tp++) |   for (tp = OtherTable; tp->name; tp++) | ||||||
|     if (strcmp (buff, tp->name) == 0) |     if (strcmp (buff, tp->name) == 0) | ||||||
|       { |       { | ||||||
| 	yylval.Number = tp->value; | 	yylval->Number = tp->value; | ||||||
| 	return tp->type; | 	return tp->type; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -822,7 +833,7 @@ LookupWord (buff) | |||||||
|       for (tp = MilitaryTable; tp->name; tp++) |       for (tp = MilitaryTable; tp->name; tp++) | ||||||
| 	if (strcmp (buff, tp->name) == 0) | 	if (strcmp (buff, tp->name) == 0) | ||||||
| 	  { | 	  { | ||||||
| 	    yylval.Number = tp->value; | 	    yylval->Number = tp->value; | ||||||
| 	    return tp->type; | 	    return tp->type; | ||||||
| 	  } | 	  } | ||||||
|     } |     } | ||||||
| @@ -838,7 +849,7 @@ LookupWord (buff) | |||||||
|     for (tp = TimezoneTable; tp->name; tp++) |     for (tp = TimezoneTable; tp->name; tp++) | ||||||
|       if (strcmp (buff, tp->name) == 0) |       if (strcmp (buff, tp->name) == 0) | ||||||
| 	{ | 	{ | ||||||
| 	  yylval.Number = tp->value; | 	  yylval->Number = tp->value; | ||||||
| 	  return tp->type; | 	  return tp->type; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -846,7 +857,9 @@ LookupWord (buff) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| yylex () | yylex (yylval, cookie) | ||||||
|  |      YYSTYPE *yylval; | ||||||
|  |      void *cookie; | ||||||
| { | { | ||||||
|   register unsigned char c; |   register unsigned char c; | ||||||
|   register char *p; |   register char *p; | ||||||
| @@ -856,42 +869,42 @@ yylex () | |||||||
|  |  | ||||||
|   for (;;) |   for (;;) | ||||||
|     { |     { | ||||||
|       while (ISSPACE ((unsigned char) *yyInput)) |       while (ISSPACE ((unsigned char) *context->yyInput)) | ||||||
| 	yyInput++; | 	context->yyInput++; | ||||||
|  |  | ||||||
|       if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') |       if (ISDIGIT (c = *context->yyInput) || c == '-' || c == '+') | ||||||
| 	{ | 	{ | ||||||
| 	  if (c == '-' || c == '+') | 	  if (c == '-' || c == '+') | ||||||
| 	    { | 	    { | ||||||
| 	      sign = c == '-' ? -1 : 1; | 	      sign = c == '-' ? -1 : 1; | ||||||
| 	      if (!ISDIGIT (*++yyInput)) | 	      if (!ISDIGIT (*++context->yyInput)) | ||||||
| 		/* skip the '-' sign */ | 		/* skip the '-' sign */ | ||||||
| 		continue; | 		continue; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    sign = 0; | 	    sign = 0; | ||||||
| 	  for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) | 	  for (yylval->Number = 0; ISDIGIT (c = *context->yyInput++);) | ||||||
| 	    yylval.Number = 10 * yylval.Number + c - '0'; | 	    yylval->Number = 10 * yylval->Number + c - '0'; | ||||||
| 	  yyInput--; | 	  context->yyInput--; | ||||||
| 	  if (sign < 0) | 	  if (sign < 0) | ||||||
| 	    yylval.Number = -yylval.Number; | 	    yylval->Number = -yylval->Number; | ||||||
| 	  return sign ? tSNUMBER : tUNUMBER; | 	  return sign ? tSNUMBER : tUNUMBER; | ||||||
| 	} | 	} | ||||||
|       if (ISALPHA (c)) |       if (ISALPHA (c)) | ||||||
| 	{ | 	{ | ||||||
| 	  for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) | 	  for (p = buff; (c = *context->yyInput++, ISALPHA (c)) || c == '.';) | ||||||
| 	    if (p < &buff[sizeof buff - 1]) | 	    if (p < &buff[sizeof buff - 1]) | ||||||
| 	      *p++ = c; | 	      *p++ = c; | ||||||
| 	  *p = '\0'; | 	  *p = '\0'; | ||||||
| 	  yyInput--; | 	  context->yyInput--; | ||||||
| 	  return LookupWord (buff); | 	  return LookupWord (yylval, buff); | ||||||
| 	} | 	} | ||||||
|       if (c != '(') |       if (c != '(') | ||||||
| 	return *yyInput++; | 	return *context->yyInput++; | ||||||
|       Count = 0; |       Count = 0; | ||||||
|       do |       do | ||||||
| 	{ | 	{ | ||||||
| 	  c = *yyInput++; | 	  c = *context->yyInput++; | ||||||
| 	  if (c == '\0') | 	  if (c == '\0') | ||||||
| 	    return c; | 	    return c; | ||||||
| 	  if (c == '(') | 	  if (c == '(') | ||||||
| @@ -931,10 +944,11 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| { | { | ||||||
|   struct tm tm, tm0, *tmp; |   struct tm tm, tm0, *tmp; | ||||||
|   time_t Start; |   time_t Start; | ||||||
|  |   CONTEXT cookie; | ||||||
| #ifdef HAVE_LOCALTIME_R | #ifdef HAVE_LOCALTIME_R | ||||||
|   struct tm keeptime; |   struct tm keeptime; | ||||||
| #endif | #endif | ||||||
|   yyInput = p; |   cookie.yyInput = p; | ||||||
|   Start = now ? *now : time ((time_t *) NULL); |   Start = now ? *now : time ((time_t *) NULL); | ||||||
| #ifdef HAVE_LOCALTIME_R | #ifdef HAVE_LOCALTIME_R | ||||||
|   tmp = (struct tm *)localtime_r(&Start, &keeptime); |   tmp = (struct tm *)localtime_r(&Start, &keeptime); | ||||||
| @@ -943,52 +957,55 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| #endif | #endif | ||||||
|   if (!tmp) |   if (!tmp) | ||||||
|     return -1; |     return -1; | ||||||
|   yyYear = tmp->tm_year + TM_YEAR_ORIGIN; |   cookie.yyYear = tmp->tm_year + TM_YEAR_ORIGIN; | ||||||
|   yyMonth = tmp->tm_mon + 1; |   cookie.yyMonth = tmp->tm_mon + 1; | ||||||
|   yyDay = tmp->tm_mday; |   cookie.yyDay = tmp->tm_mday; | ||||||
|   yyHour = tmp->tm_hour; |   cookie.yyHour = tmp->tm_hour; | ||||||
|   yyMinutes = tmp->tm_min; |   cookie.yyMinutes = tmp->tm_min; | ||||||
|   yySeconds = tmp->tm_sec; |   cookie.yySeconds = tmp->tm_sec; | ||||||
|   tm.tm_isdst = tmp->tm_isdst; |   tm.tm_isdst = tmp->tm_isdst; | ||||||
|   yyMeridian = MER24; |   cookie.yyMeridian = MER24; | ||||||
|   yyRelSeconds = 0; |   cookie.yyRelSeconds = 0; | ||||||
|   yyRelMinutes = 0; |   cookie.yyRelMinutes = 0; | ||||||
|   yyRelHour = 0; |   cookie.yyRelHour = 0; | ||||||
|   yyRelDay = 0; |   cookie.yyRelDay = 0; | ||||||
|   yyRelMonth = 0; |   cookie.yyRelMonth = 0; | ||||||
|   yyRelYear = 0; |   cookie.yyRelYear = 0; | ||||||
|   yyHaveDate = 0; |   cookie.yyHaveDate = 0; | ||||||
|   yyHaveDay = 0; |   cookie.yyHaveDay = 0; | ||||||
|   yyHaveRel = 0; |   cookie.yyHaveRel = 0; | ||||||
|   yyHaveTime = 0; |   cookie.yyHaveTime = 0; | ||||||
|   yyHaveZone = 0; |   cookie.yyHaveZone = 0; | ||||||
|  |  | ||||||
|   if (yyparse () |   if (yyparse (&cookie) | ||||||
|       || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) |       || cookie.yyHaveTime > 1 || cookie.yyHaveZone > 1 || | ||||||
|  |       cookie.yyHaveDate > 1 || cookie.yyHaveDay > 1) | ||||||
|     return -1; |     return -1; | ||||||
|  |  | ||||||
|   tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; |   tm.tm_year = ToYear (cookie.yyYear) - TM_YEAR_ORIGIN + cookie.yyRelYear; | ||||||
|   tm.tm_mon = yyMonth - 1 + yyRelMonth; |   tm.tm_mon = cookie.yyMonth - 1 + cookie.yyRelMonth; | ||||||
|   tm.tm_mday = yyDay + yyRelDay; |   tm.tm_mday = cookie.yyDay + cookie.yyRelDay; | ||||||
|   if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) |   if (cookie.yyHaveTime || | ||||||
|  |       (cookie.yyHaveRel && !cookie.yyHaveDate && !cookie.yyHaveDay)) | ||||||
|     { |     { | ||||||
|       tm.tm_hour = ToHour (yyHour, yyMeridian); |       tm.tm_hour = ToHour (cookie.yyHour, cookie.yyMeridian); | ||||||
|       if (tm.tm_hour < 0) |       if (tm.tm_hour < 0) | ||||||
| 	return -1; | 	return -1; | ||||||
|       tm.tm_min = yyMinutes; |       tm.tm_min = cookie.yyMinutes; | ||||||
|       tm.tm_sec = yySeconds; |       tm.tm_sec = cookie.yySeconds; | ||||||
|     } |     } | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       tm.tm_hour = tm.tm_min = tm.tm_sec = 0; |       tm.tm_hour = tm.tm_min = tm.tm_sec = 0; | ||||||
|     } |     } | ||||||
|   tm.tm_hour += yyRelHour; |   tm.tm_hour += cookie.yyRelHour; | ||||||
|   tm.tm_min += yyRelMinutes; |   tm.tm_min += cookie.yyRelMinutes; | ||||||
|   tm.tm_sec += yyRelSeconds; |   tm.tm_sec += cookie.yyRelSeconds; | ||||||
|  |  | ||||||
|   /* Let mktime deduce tm_isdst if we have an absolute timestamp, |   /* Let mktime deduce tm_isdst if we have an absolute timestamp, | ||||||
|      or if the relative timestamp mentions days, months, or years.  */ |      or if the relative timestamp mentions days, months, or years.  */ | ||||||
|   if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear) |   if (cookie.yyHaveDate | cookie.yyHaveDay | cookie.yyHaveTime | | ||||||
|  |       cookie.yyRelDay | cookie.yyRelMonth | cookie.yyRelYear) | ||||||
|     tm.tm_isdst = -1; |     tm.tm_isdst = -1; | ||||||
|  |  | ||||||
|   tm0 = tm; |   tm0 = tm; | ||||||
| @@ -1006,18 +1023,18 @@ curl_getdate (const char *p, const time_t *now) | |||||||
|          we apply mktime to 1970-01-02 08:00:00 instead and adjust the time |          we apply mktime to 1970-01-02 08:00:00 instead and adjust the time | ||||||
|          zone by 24 hours to compensate.  This algorithm assumes that |          zone by 24 hours to compensate.  This algorithm assumes that | ||||||
|          there is no DST transition within a day of the time_t boundaries.  */ |          there is no DST transition within a day of the time_t boundaries.  */ | ||||||
|       if (yyHaveZone) |       if (cookie.yyHaveZone) | ||||||
| 	{ | 	{ | ||||||
| 	  tm = tm0; | 	  tm = tm0; | ||||||
| 	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) | 	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) | ||||||
| 	    { | 	    { | ||||||
| 	      tm.tm_mday++; | 	      tm.tm_mday++; | ||||||
| 	      yyTimezone -= 24 * 60; | 	      cookie.yyTimezone -= 24 * 60; | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
| 	      tm.tm_mday--; | 	      tm.tm_mday--; | ||||||
| 	      yyTimezone += 24 * 60; | 	      cookie.yyTimezone += 24 * 60; | ||||||
| 	    } | 	    } | ||||||
| 	  Start = mktime (&tm); | 	  Start = mktime (&tm); | ||||||
| 	} | 	} | ||||||
| @@ -1026,22 +1043,29 @@ curl_getdate (const char *p, const time_t *now) | |||||||
| 	return Start; | 	return Start; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (yyHaveDay && !yyHaveDate) |   if (cookie.yyHaveDay && !cookie.yyHaveDate) | ||||||
|     { |     { | ||||||
|       tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 |       tm.tm_mday += ((cookie.yyDayNumber - tm.tm_wday + 7) % 7 | ||||||
| 		     + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); | 		     + 7 * (cookie.yyDayOrdinal - (0 < cookie.yyDayOrdinal))); | ||||||
|       Start = mktime (&tm); |       Start = mktime (&tm); | ||||||
|       if (Start == (time_t) -1) |       if (Start == (time_t) -1) | ||||||
| 	return Start; | 	return Start; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (yyHaveZone) |   if (cookie.yyHaveZone) | ||||||
|     { |     { | ||||||
|       long delta; |       long delta; | ||||||
|       struct tm *gmt = gmtime (&Start); |       struct tm *gmt; | ||||||
|  | #ifdef HAVE_GMTIME_R | ||||||
|  |       /* thread-safe version */ | ||||||
|  |       struct tm keeptime; | ||||||
|  |       gmt = (struct tm *)gmtime_r(&Start, &keeptime); | ||||||
|  | #else | ||||||
|  |       gmt = gmtime(&Start); | ||||||
|  | #endif | ||||||
|       if (!gmt) |       if (!gmt) | ||||||
| 	return -1; | 	return -1; | ||||||
|       delta = yyTimezone * 60L + difftm (&tm, gmt); |       delta = cookie.yyTimezone * 60L + difftm (&tm, gmt); | ||||||
|       if ((Start + delta < Start) != (delta < 0)) |       if ((Start + delta < Start) != (delta < 0)) | ||||||
| 	return -1;		/* time_t overflow */ | 	return -1;		/* time_t overflow */ | ||||||
|       Start += delta; |       Start += delta; | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ | |||||||
|  * $Id$ |  * $Id$ | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @@ -53,7 +55,6 @@ char *GetEnv(const char *variable) | |||||||
|   if (env && strcmp("HOME",variable) == 0) { |   if (env && strcmp("HOME",variable) == 0) { | ||||||
| 	env = decc$translate_vms(env); | 	env = decc$translate_vms(env); | ||||||
|   } |   } | ||||||
| /*  printf ("Getenv: %s=%s\n",variable,env); */ |  | ||||||
| #else | #else | ||||||
|   /* no length control */ |   /* no length control */ | ||||||
|   char *env = getenv(variable); |   char *env = getenv(variable); | ||||||
|   | |||||||
| @@ -31,6 +31,10 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|  |  | ||||||
|  | #ifdef	VMS | ||||||
|  | #include	<stdlib.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * This is supposed to be called in the beginning of a permform() session |  * This is supposed to be called in the beginning of a permform() session | ||||||
|  * and should reset all session-info variables |  * and should reset all session-info variables | ||||||
| @@ -43,11 +47,19 @@ CURLcode Curl_initinfo(struct SessionHandle *data) | |||||||
|   pro->t_nslookup = 0; |   pro->t_nslookup = 0; | ||||||
|   pro->t_connect = 0; |   pro->t_connect = 0; | ||||||
|   pro->t_pretransfer = 0; |   pro->t_pretransfer = 0; | ||||||
|  |   pro->t_starttransfer = 0; | ||||||
|  |   pro->timespent = 0; | ||||||
|  |  | ||||||
|   info->httpcode = 0; |   info->httpcode = 0; | ||||||
|   info->httpversion=0; |   info->httpversion=0; | ||||||
|   info->filetime=-1; /* -1 is an illegal time and thus means unknown */ |   info->filetime=-1; /* -1 is an illegal time and thus means unknown */ | ||||||
|    |    | ||||||
|  |   if (info->contenttype) | ||||||
|  |     free(info->contenttype); | ||||||
|  |   info->contenttype = NULL; | ||||||
|  |  | ||||||
|  |   info->header_size = 0; | ||||||
|  |   info->request_size = 0; | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -107,6 +119,9 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) | |||||||
|   case CURLINFO_PRETRANSFER_TIME: |   case CURLINFO_PRETRANSFER_TIME: | ||||||
|     *param_doublep =  data->progress.t_pretransfer; |     *param_doublep =  data->progress.t_pretransfer; | ||||||
|     break; |     break; | ||||||
|  |   case CURLINFO_STARTTRANSFER_TIME: | ||||||
|  |     *param_doublep = data->progress.t_starttransfer; | ||||||
|  |     break; | ||||||
|   case CURLINFO_SIZE_UPLOAD: |   case CURLINFO_SIZE_UPLOAD: | ||||||
|     *param_doublep =  data->progress.uploaded; |     *param_doublep =  data->progress.uploaded; | ||||||
|     break; |     break; | ||||||
| @@ -128,6 +143,9 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) | |||||||
|   case CURLINFO_CONTENT_LENGTH_UPLOAD: |   case CURLINFO_CONTENT_LENGTH_UPLOAD: | ||||||
|     *param_doublep = data->progress.size_ul; |     *param_doublep = data->progress.size_ul; | ||||||
|     break; |     break; | ||||||
|  |   case CURLINFO_CONTENT_TYPE: | ||||||
|  |     *param_charp = data->info.contenttype; | ||||||
|  |     break; | ||||||
|   default: |   default: | ||||||
|     return CURLE_BAD_FUNCTION_ARGUMENT; |     return CURLE_BAD_FUNCTION_ARGUMENT; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -35,9 +35,7 @@ | |||||||
|  *   Daniel Stenberg <daniel@haxx.se> |  *   Daniel Stenberg <daniel@haxx.se> | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifdef HAVE_CONFIG_H | #include "setup.h" /* setup.h is required for read() prototype */ | ||||||
| #  include <config.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef HAVE_GETPASS_R | #ifndef HAVE_GETPASS_R | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										285
									
								
								lib/hash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								lib/hash.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,285 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include "hash.h" | ||||||
|  | #include "llist.h" | ||||||
|  |  | ||||||
|  | #ifdef MALLOCDEBUG | ||||||
|  | /* this must be the last include file */ | ||||||
|  | #include "memdebug.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static unsigned long  | ||||||
|  | curl_hash_str(const char *key, unsigned int key_length) | ||||||
|  | { | ||||||
|  |   register unsigned long h = 0; | ||||||
|  |   register unsigned long g; | ||||||
|  |   register char *p = (char *) key; | ||||||
|  |   register char *end = (char *) key + key_length; | ||||||
|  |  | ||||||
|  |   while (p < end) { | ||||||
|  |     h = (h << 4) + *p++; | ||||||
|  |     if ((g = (h & 0xF0000000))) { | ||||||
|  |       h = h ^ (g >> 24); | ||||||
|  |       h = h ^ g; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return h; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned long  | ||||||
|  | curl_hash_num(unsigned long key) | ||||||
|  | { | ||||||
|  |   key += ~(key << 15); | ||||||
|  |   key ^= (key >> 10); | ||||||
|  |   key += (key << 3); | ||||||
|  |   key ^= (key >> 6); | ||||||
|  |   key += (key << 11); | ||||||
|  |   key ^= (key >> 16); | ||||||
|  |  | ||||||
|  |   return key; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void  | ||||||
|  | hash_element_dtor(void *u, void *ele) | ||||||
|  | { | ||||||
|  |   curl_hash_element *e = (curl_hash_element *) ele;  | ||||||
|  |   curl_hash         *h = (curl_hash *) u;  | ||||||
|  | 	 | ||||||
|  |   if (e->key.type == CURL_HASH_KEY_IS_STRING) { | ||||||
|  |     free(e->key.value.str.val); | ||||||
|  |   } | ||||||
|  |   h->dtor(e->ptr); | ||||||
|  |  | ||||||
|  |   free(e); | ||||||
|  |   e = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void  | ||||||
|  | curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |  | ||||||
|  |   h->dtor = dtor; | ||||||
|  |   h->size = 0; | ||||||
|  |   h->slots = slots;   | ||||||
|  |  | ||||||
|  |   h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *)); | ||||||
|  |   for (i = 0; i < h->slots; ++i) { | ||||||
|  |     h->table[i] = curl_llist_alloc((curl_llist_dtor) hash_element_dtor); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | curl_hash * | ||||||
|  | curl_hash_alloc(int slots, curl_hash_dtor dtor) | ||||||
|  | { | ||||||
|  |   curl_hash *h; | ||||||
|  |  | ||||||
|  |   h = (curl_hash *)malloc(sizeof(curl_hash)); | ||||||
|  |   if(NULL == h) | ||||||
|  |     return NULL; | ||||||
|  |  | ||||||
|  |   curl_hash_init(h, slots, dtor); | ||||||
|  |  | ||||||
|  |   return h; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define FIND_SLOT(__h, __s_key, __s_key_len, __n_key) \ | ||||||
|  |   ((__s_key ? curl_hash_str(__s_key, __s_key_len) : curl_hash_num(__n_key)) % (__h)->slots) | ||||||
|  |  | ||||||
|  | #define KEY_CREATE(__k, __s_key, __s_key_len, __n_key, __dup) \ | ||||||
|  |   if (__s_key) { \ | ||||||
|  |     if (__dup) { \ | ||||||
|  |       (__k)->value.str.val = (char *) malloc(__s_key_len); \ | ||||||
|  |       memcpy((__k)->value.str.val, __s_key, __s_key_len); \ | ||||||
|  |     } else { \ | ||||||
|  |       (__k)->value.str.val = __s_key; \ | ||||||
|  |     } \ | ||||||
|  |     (__k)->value.str.len = __s_key_len; \ | ||||||
|  |     (__k)->type = CURL_HASH_KEY_IS_STRING; \ | ||||||
|  |   } else { \ | ||||||
|  |     (__k)->value.num = __n_key; \ | ||||||
|  |     (__k)->type = CURL_HASH_KEY_IS_NUM; \ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | #define MIN(a, b) (a > b ? b : a) | ||||||
|  |  | ||||||
|  | static int  | ||||||
|  | curl_hash_key_compare(curl_hash_key *key1, curl_hash_key *key2) | ||||||
|  | { | ||||||
|  |   if (key1->type == CURL_HASH_KEY_IS_NUM) { | ||||||
|  |     if (key2->type == CURL_HASH_KEY_IS_STRING) | ||||||
|  |       return 0; | ||||||
|  |  | ||||||
|  |     if (key1->value.num == key2->value.num) | ||||||
|  |       return 1; | ||||||
|  |   } else { | ||||||
|  |     if (key2->type == CURL_HASH_KEY_IS_NUM) | ||||||
|  |       return 0; | ||||||
|  |  | ||||||
|  |     if (memcmp(key1->value.str.val, key2->value.str.val,  | ||||||
|  |                MIN(key1->value.str.len, key2->value.str.len)) == 0) | ||||||
|  |       return 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  |                         unsigned long num_key, const void *p) | ||||||
|  | { | ||||||
|  |   curl_hash_element  *e; | ||||||
|  |   curl_hash_key       tmp; | ||||||
|  |   curl_llist         *l;  | ||||||
|  |   curl_llist_element *le; | ||||||
|  |   int                slot; | ||||||
|  |  | ||||||
|  |   slot = FIND_SLOT(h, str_key, str_key_len, num_key); | ||||||
|  |   l = h->table[slot]; | ||||||
|  |   KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); | ||||||
|  |   for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { | ||||||
|  |     if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { | ||||||
|  |       curl_hash_element *to_update = CURL_LLIST_VALP(le); | ||||||
|  |       h->dtor(to_update->ptr); | ||||||
|  |       to_update->ptr = (void *) p; | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   e = (curl_hash_element *) malloc(sizeof(curl_hash_element)); | ||||||
|  |   KEY_CREATE(&e->key, str_key, str_key_len, num_key, 1); | ||||||
|  |   e->ptr = (void *) p; | ||||||
|  |  | ||||||
|  |   if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), e)) { | ||||||
|  |     ++h->size; | ||||||
|  |     return 1; | ||||||
|  |   } else { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  |                           unsigned long num_key) | ||||||
|  | { | ||||||
|  |   curl_llist         *l; | ||||||
|  |   curl_llist_element *le; | ||||||
|  |   curl_hash_key       tmp; | ||||||
|  |   int                slot; | ||||||
|  |  | ||||||
|  |   slot = FIND_SLOT(h, str_key, str_key_len, num_key); | ||||||
|  |   l = h->table[slot]; | ||||||
|  |  | ||||||
|  |   KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); | ||||||
|  |   for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { | ||||||
|  |     if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { | ||||||
|  |       curl_llist_remove(l, le, (void *) h); | ||||||
|  |       --h->size; | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  |                         unsigned long num_key, void **p) | ||||||
|  | { | ||||||
|  |   curl_llist         *l; | ||||||
|  |   curl_llist_element *le; | ||||||
|  |   curl_hash_key       tmp; | ||||||
|  |   int                slot; | ||||||
|  |  | ||||||
|  |   slot = FIND_SLOT(h, str_key, str_key_len, num_key); | ||||||
|  |   l = h->table[slot]; | ||||||
|  |  | ||||||
|  |   KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); | ||||||
|  |   for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { | ||||||
|  |     if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { | ||||||
|  |       *p = ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr; | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void  | ||||||
|  | curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *)) | ||||||
|  | { | ||||||
|  |   curl_llist_element  *le; | ||||||
|  |   int                  i; | ||||||
|  |  | ||||||
|  |   for (i = 0; i < h->slots; ++i) { | ||||||
|  |     for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) { | ||||||
|  |       cb(user, (curl_hash_element *) CURL_LLIST_VALP(le)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | curl_hash_clean(curl_hash *h) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |  | ||||||
|  |   for (i = 0; i < h->slots; ++i) { | ||||||
|  |     curl_llist_destroy(h->table[i], (void *) h); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   free(h->table); | ||||||
|  |   h->table = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t  | ||||||
|  | curl_hash_count(curl_hash *h) | ||||||
|  | { | ||||||
|  |   return h->size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void  | ||||||
|  | curl_hash_destroy(curl_hash *h) | ||||||
|  | { | ||||||
|  |   if (!h) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   curl_hash_clean(h); | ||||||
|  |   free(h); | ||||||
|  |   h = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * local variables: | ||||||
|  |  * eval: (load-file "../curl-mode.el") | ||||||
|  |  * end: | ||||||
|  |  * vim600: fdm=marker | ||||||
|  |  * vim: et sw=2 ts=2 sts=2 tw=78 | ||||||
|  |  */ | ||||||
							
								
								
									
										85
									
								
								lib/hash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								lib/hash.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | #ifndef __HASH_H | ||||||
|  | #define __HASH_H | ||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | #include "llist.h" | ||||||
|  |  | ||||||
|  | #define CURL_HASH_KEY_IS_STRING 0 | ||||||
|  | #define CURL_HASH_KEY_IS_NUM    1 | ||||||
|  |  | ||||||
|  | typedef void (*curl_hash_dtor)(void *); | ||||||
|  |  | ||||||
|  | typedef struct _curl_hash { | ||||||
|  |   curl_llist     **table; | ||||||
|  |   curl_hash_dtor   dtor; | ||||||
|  |   int              slots; | ||||||
|  |   size_t           size; | ||||||
|  | } curl_hash; | ||||||
|  |  | ||||||
|  | typedef struct _curl_hash_key { | ||||||
|  |   union { | ||||||
|  |     struct { | ||||||
|  |       char *val; | ||||||
|  |       unsigned int len; | ||||||
|  |     } str; | ||||||
|  |  | ||||||
|  |     unsigned long num; | ||||||
|  |   } value; | ||||||
|  |  | ||||||
|  |   int type; | ||||||
|  | } curl_hash_key; | ||||||
|  |  | ||||||
|  | typedef struct _curl_hash_element { | ||||||
|  |   curl_hash_key  key; | ||||||
|  |   void          *ptr; | ||||||
|  | } curl_hash_element; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor); | ||||||
|  | curl_hash *curl_hash_alloc(int slots, curl_hash_dtor dtor); | ||||||
|  | int curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  | 			     unsigned long num_key, const void *p); | ||||||
|  | int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  | 			       unsigned long num_key); | ||||||
|  | int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,  | ||||||
|  | 			     unsigned long num_key, void **p); | ||||||
|  | void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *)); | ||||||
|  | size_t curl_hash_count(curl_hash *h); | ||||||
|  | void curl_hash_clean(curl_hash *h); | ||||||
|  | void curl_hash_destroy(curl_hash *h); | ||||||
|  |  | ||||||
|  | #define curl_hash_find(h, key, key_len, p) curl_hash_extended_find(h, key, key_len, 0, p) | ||||||
|  | #define curl_hash_delete(h, key, key_len) curl_hash_extended_delete(h, key, key_len, 0) | ||||||
|  | #define curl_hash_add(h, key, key_len, p) curl_hash_add_or_update(h, key, key_len, 0, p) | ||||||
|  | #define curl_hash_update curl_hash_add | ||||||
|  | #define curl_hash_index_find(h, key, p) curl_hash_extended_find(h, NULL, 0, key, p) | ||||||
|  | #define curl_hash_index_delete(h, key) curl_hash_extended_delete(h, NULL, 0, key) | ||||||
|  | #define curl_hash_index_add(h, key, p) curl_hash_add_or_update(h, NULL, 0, key, p) | ||||||
|  | #define curl_hash_index_update curl_hash_index_add | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										183
									
								
								lib/hostip.c
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								lib/hostip.c
									
									
									
									
									
								
							| @@ -28,7 +28,6 @@ | |||||||
|  |  | ||||||
| #define _REENTRANT | #define _REENTRANT | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) | #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) | ||||||
| #include <winsock.h> | #include <winsock.h> | ||||||
| #else | #else | ||||||
| @@ -47,7 +46,11 @@ | |||||||
| #ifdef HAVE_ARPA_INET_H | #ifdef HAVE_ARPA_INET_H | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
| #endif | #endif | ||||||
|  | #ifdef HAVE_STDLIB_H | ||||||
|  | #include <stdlib.h>	/* required for free() prototypes */ | ||||||
|  | #endif | ||||||
| #ifdef	VMS | #ifdef	VMS | ||||||
|  | #include <in.h> | ||||||
| #include <inet.h> | #include <inet.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #endif | #endif | ||||||
| @@ -56,6 +59,10 @@ | |||||||
| #include "urldata.h" | #include "urldata.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
| #include "hostip.h" | #include "hostip.h" | ||||||
|  | #include "hash.h" | ||||||
|  |  | ||||||
|  | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
|  | #include <curl/mprintf.h> | ||||||
|  |  | ||||||
| #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) | #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) | ||||||
| #include "inet_ntoa_r.h" | #include "inet_ntoa_r.h" | ||||||
| @@ -66,6 +73,151 @@ | |||||||
| #include "memdebug.h" | #include "memdebug.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | static curl_hash hostname_cache; | ||||||
|  | static int host_cache_initialized; | ||||||
|  |  | ||||||
|  | void Curl_global_host_cache_init(void) | ||||||
|  | { | ||||||
|  |   if (!host_cache_initialized) { | ||||||
|  |     curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo); | ||||||
|  |     host_cache_initialized = 1; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | curl_hash *Curl_global_host_cache_get(void) | ||||||
|  | { | ||||||
|  |   return &hostname_cache; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Curl_global_host_cache_dtor(void) | ||||||
|  | { | ||||||
|  |   if (host_cache_initialized) { | ||||||
|  |     curl_hash_clean(&hostname_cache); | ||||||
|  |     host_cache_initialized = 0; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct curl_dns_cache_entry { | ||||||
|  |   Curl_addrinfo *addr; | ||||||
|  |   time_t timestamp; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* count the number of characters that an integer takes up */ | ||||||
|  | static int _num_chars(int i) | ||||||
|  | { | ||||||
|  |   int chars = 0; | ||||||
|  |  | ||||||
|  |   /* While the number divided by 10 is greater than one,  | ||||||
|  |    * re-divide the number by 10, and increment the number of  | ||||||
|  |    * characters by 1. | ||||||
|  |    * | ||||||
|  |    * this relies on the fact that for every multiple of 10,  | ||||||
|  |    * a new digit is added onto every number | ||||||
|  |    */ | ||||||
|  |   do { | ||||||
|  |     chars++; | ||||||
|  |  | ||||||
|  |     i = (int) i / 10; | ||||||
|  |   } while (i >= 1); | ||||||
|  |  | ||||||
|  |   return chars; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Create a hostcache id */ | ||||||
|  | static char * | ||||||
|  | _create_hostcache_id(char *server, int port, ssize_t *entry_len) | ||||||
|  | { | ||||||
|  |   char *id = NULL; | ||||||
|  |  | ||||||
|  |   /* Get the length of the new entry id */ | ||||||
|  |   *entry_len = *entry_len +      /* Hostname length */ | ||||||
|  |                1 +               /* The ':' seperator */ | ||||||
|  |                _num_chars(port); /* The number of characters the port will take up */ | ||||||
|  |    | ||||||
|  |   /* Allocate the new entry id */ | ||||||
|  |   id = malloc(*entry_len + 1); | ||||||
|  |   if (!id) { | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* Create the new entry */ | ||||||
|  |   /* If sprintf() doesn't return the entry length, that signals failure */ | ||||||
|  |   if (sprintf(id, "%s:%d", server, port) != *entry_len) { | ||||||
|  |     /* Free the allocated id, set length to zero and return NULL */ | ||||||
|  |     *entry_len = 0; | ||||||
|  |     free(id); | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return id; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Macro to save redundant free'ing of entry_id */ | ||||||
|  | #define _hostcache_return(__v) \ | ||||||
|  | { \ | ||||||
|  |   free(entry_id); \ | ||||||
|  |   return (__v); \ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Curl_addrinfo *Curl_resolv(struct SessionHandle *data, | ||||||
|  |                            char *hostname, | ||||||
|  |                            int port, | ||||||
|  |                            char **bufp) | ||||||
|  | { | ||||||
|  |   char *entry_id = NULL; | ||||||
|  |   struct curl_dns_cache_entry *p = NULL; | ||||||
|  |   ssize_t entry_len; | ||||||
|  |   time_t now; | ||||||
|  |  | ||||||
|  |   /* If the host cache timeout is 0, we don't do DNS cach'ing | ||||||
|  |      so fall through */ | ||||||
|  |   if (data->set.dns_cache_timeout == 0) { | ||||||
|  |     return Curl_getaddrinfo(data, hostname, port, bufp); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* Create an entry id, based upon the hostname and port */ | ||||||
|  |   entry_len = strlen(hostname); | ||||||
|  |   entry_id = _create_hostcache_id(hostname, port, &entry_len); | ||||||
|  |   /* If we can't create the entry id, don't cache, just fall-through | ||||||
|  |      to the plain Curl_getaddrinfo() */ | ||||||
|  |   if (!entry_id) { | ||||||
|  |     return Curl_getaddrinfo(data, hostname, port, bufp); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   time(&now); | ||||||
|  |   /* See if its already in our dns cache */ | ||||||
|  |   if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) { | ||||||
|  |     /* Do we need to check for a cache timeout? */ | ||||||
|  |     if (data->set.dns_cache_timeout != -1) { | ||||||
|  |       /* Return if the entry has not timed out */ | ||||||
|  |       if ((now - p->timestamp) < data->set.dns_cache_timeout) { | ||||||
|  |         _hostcache_return(p->addr); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       _hostcache_return(p->addr); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* Create a new cache entry */ | ||||||
|  |   p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry)); | ||||||
|  |   if (!p) { | ||||||
|  |    _hostcache_return(NULL); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   p->addr = Curl_getaddrinfo(data, hostname, port, bufp); | ||||||
|  |   if (!p->addr) { | ||||||
|  |     free(p); | ||||||
|  |     _hostcache_return(NULL); | ||||||
|  |   } | ||||||
|  |   p->timestamp = now; | ||||||
|  |  | ||||||
|  |   /* Save it in our host cache */ | ||||||
|  |   curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p); | ||||||
|  |  | ||||||
|  |   _hostcache_return(p->addr); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * This is a wrapper function for freeing name information in a protocol |  * This is a wrapper function for freeing name information in a protocol | ||||||
|  * independent way. This takes care of using the appropriate underlaying |  * independent way. This takes care of using the appropriate underlaying | ||||||
| @@ -73,11 +225,15 @@ | |||||||
|  */ |  */ | ||||||
| void Curl_freeaddrinfo(void *freethis) | void Curl_freeaddrinfo(void *freethis) | ||||||
| { | { | ||||||
|  |   struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis; | ||||||
|  |  | ||||||
| #ifdef ENABLE_IPV6 | #ifdef ENABLE_IPV6 | ||||||
|   freeaddrinfo(freethis); |   freeaddrinfo(p->addr); | ||||||
| #else | #else | ||||||
|   free(freethis); |   free(p->addr); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |   free(p); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* --- resolve name or IP-number --- */ | /* --- resolve name or IP-number --- */ | ||||||
| @@ -100,7 +256,7 @@ int curl_getaddrinfo(char *hostname, char *service, | |||||||
|     /* success */ |     /* success */ | ||||||
|     if(logfile) |     if(logfile) | ||||||
|       fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n", |       fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n", | ||||||
|               source, line, *result); |               source, line, (void *)*result); | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     if(logfile) |     if(logfile) | ||||||
| @@ -116,7 +272,7 @@ void curl_freeaddrinfo(struct addrinfo *freethis, | |||||||
|   (freeaddrinfo)(freethis); |   (freeaddrinfo)(freethis); | ||||||
|   if(logfile) |   if(logfile) | ||||||
|     fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n", |     fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n", | ||||||
|             source, line, freethis); |             source, line, (void *)freethis); | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| @@ -137,7 +293,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|   char sbuf[NI_MAXSERV]; |   char sbuf[NI_MAXSERV]; | ||||||
|  |  | ||||||
|   memset(&hints, 0, sizeof(hints)); |   memset(&hints, 0, sizeof(hints)); | ||||||
|   hints.ai_family = PF_UNSPEC; |   hints.ai_family = PF_INET; | ||||||
|   hints.ai_socktype = SOCK_STREAM; |   hints.ai_socktype = SOCK_STREAM; | ||||||
|   hints.ai_flags = AI_CANONNAME; |   hints.ai_flags = AI_CANONNAME; | ||||||
|   snprintf(sbuf, sizeof(sbuf), "%d", port); |   snprintf(sbuf, sizeof(sbuf), "%d", port); | ||||||
| @@ -254,7 +410,7 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len) | |||||||
|    considerably. */ |    considerably. */ | ||||||
|  |  | ||||||
| #ifndef INADDR_NONE | #ifndef INADDR_NONE | ||||||
| #define INADDR_NONE (unsigned long) ~0 | #define INADDR_NONE (in_addr_t) ~0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | ||||||
| @@ -263,7 +419,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|                                 char **bufp) |                                 char **bufp) | ||||||
| { | { | ||||||
|   struct hostent *h = NULL; |   struct hostent *h = NULL; | ||||||
|   unsigned long in; |   in_addr_t in; | ||||||
|   int ret; /* this variable is unused on several platforms but used on some */ |   int ret; /* this variable is unused on several platforms but used on some */ | ||||||
|  |  | ||||||
| #define CURL_NAMELOOKUP_SIZE 9000 | #define CURL_NAMELOOKUP_SIZE 9000 | ||||||
| @@ -271,10 +427,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|    * everything. OSF1 is known to require at least 8872 bytes. The buffer |    * everything. OSF1 is known to require at least 8872 bytes. The buffer | ||||||
|    * required for storing all possible aliases and IP numbers is according to |    * required for storing all possible aliases and IP numbers is according to | ||||||
|    * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */ |    * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */ | ||||||
|   char *buf = (char *)malloc(CURL_NAMELOOKUP_SIZE); |   int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE); | ||||||
|   if(!buf) |   if(!buf) | ||||||
|     return NULL; /* major failure */ |     return NULL; /* major failure */ | ||||||
|   *bufp = buf; |   *bufp = (char *)buf; | ||||||
|  |  | ||||||
|   port=0; /* unused in IPv4 code */ |   port=0; /* unused in IPv4 code */ | ||||||
|   ret = 0; /* to prevent the compiler warning */ |   ret = 0; /* to prevent the compiler warning */ | ||||||
| @@ -304,7 +460,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|     /* Solaris, IRIX and more */ |     /* Solaris, IRIX and more */ | ||||||
|     if ((h = gethostbyname_r(hostname, |     if ((h = gethostbyname_r(hostname, | ||||||
|                              (struct hostent *)buf, |                              (struct hostent *)buf, | ||||||
|                              buf + sizeof(struct hostent), |                              (char *)buf + sizeof(struct hostent), | ||||||
|                              CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), |                              CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), | ||||||
|                              &h_errnop)) == NULL ) |                              &h_errnop)) == NULL ) | ||||||
| #endif | #endif | ||||||
| @@ -312,7 +468,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|     /* Linux */ |     /* Linux */ | ||||||
|     if( gethostbyname_r(hostname, |     if( gethostbyname_r(hostname, | ||||||
|                         (struct hostent *)buf, |                         (struct hostent *)buf, | ||||||
|                         buf + sizeof(struct hostent), |                         (char *)buf + sizeof(struct hostent), | ||||||
|                         CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), |                         CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), | ||||||
|                         &h, /* DIFFERENCE */ |                         &h, /* DIFFERENCE */ | ||||||
|                         &h_errnop)) |                         &h_errnop)) | ||||||
| @@ -355,7 +511,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|       /* we make a copy of the hostent right now, right here, as the |       /* we make a copy of the hostent right now, right here, as the | ||||||
|          static one we got a pointer to might get removed when we don't |          static one we got a pointer to might get removed when we don't | ||||||
|          want/expect that */ |          want/expect that */ | ||||||
|       h = pack_hostent(buf, h); |       h = pack_hostent((char *)buf, h); | ||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|   return (h); |   return (h); | ||||||
| @@ -370,3 +526,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | |||||||
|  * vim600: fdm=marker |  * vim600: fdm=marker | ||||||
|  * vim: et sw=2 ts=2 sts=2 tw=78 |  * vim: et sw=2 ts=2 sts=2 tw=78 | ||||||
|  */ |  */ | ||||||
|  |   | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								lib/hostip.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								lib/hostip.h
									
									
									
									
									
								
							| @@ -23,10 +23,23 @@ | |||||||
|  * $Id$ |  * $Id$ | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "hash.h" | ||||||
|  |  | ||||||
| struct addrinfo; | struct addrinfo; | ||||||
| struct hostent; | struct hostent; | ||||||
| struct SessionHandle; | struct SessionHandle; | ||||||
|  |  | ||||||
|  | void Curl_global_host_cache_init(void); | ||||||
|  | void Curl_global_host_cache_dtor(void); | ||||||
|  | curl_hash *Curl_global_host_cache_get(void); | ||||||
|  |  | ||||||
|  | #define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache) | ||||||
|  |  | ||||||
|  | Curl_addrinfo *Curl_resolv(struct SessionHandle *data, | ||||||
|  | 			   char *hostname, | ||||||
|  | 			   int port, | ||||||
|  | 			   char **bufp); | ||||||
|  |  | ||||||
| /* Get name info */ | /* Get name info */ | ||||||
| Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, | ||||||
|                                 char *hostname, |                                 char *hostname, | ||||||
|   | |||||||
							
								
								
									
										221
									
								
								lib/http.c
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								lib/http.c
									
									
									
									
									
								
							| @@ -128,8 +128,10 @@ static | |||||||
| CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, | CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, | ||||||
|                          long *bytes_written) |                          long *bytes_written) | ||||||
| { | { | ||||||
|   size_t amount; |   ssize_t amount; | ||||||
|   CURLcode result; |   CURLcode res; | ||||||
|  |   char *ptr; | ||||||
|  |   int size; | ||||||
|  |  | ||||||
|   if(conn->data->set.verbose) { |   if(conn->data->set.verbose) { | ||||||
|     fputs("> ", conn->data->set.err); |     fputs("> ", conn->data->set.err); | ||||||
| @@ -137,7 +139,25 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, | |||||||
|     fwrite(in->buffer, in->size_used, 1, conn->data->set.err); |     fwrite(in->buffer, in->size_used, 1, conn->data->set.err); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount); |   /* The looping below is required since we use non-blocking sockets, but due | ||||||
|  |      to the circumstances we will just loop and try again and again etc */ | ||||||
|  |  | ||||||
|  |   ptr = in->buffer; | ||||||
|  |   size = in->size_used; | ||||||
|  |   do { | ||||||
|  |     res = Curl_write(conn, sockfd, ptr, size, &amount); | ||||||
|  |  | ||||||
|  |     if(CURLE_OK != res) | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |     if(amount != size) { | ||||||
|  |       size -= amount; | ||||||
|  |       ptr += amount; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |   } while(1); | ||||||
|  |  | ||||||
|   if(in->buffer) |   if(in->buffer) | ||||||
|     free(in->buffer); |     free(in->buffer); | ||||||
| @@ -145,7 +165,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, | |||||||
|  |  | ||||||
|   *bytes_written = amount; |   *bytes_written = amount; | ||||||
|  |  | ||||||
|   return result; |   return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -204,28 +224,6 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size) | |||||||
| /* end of the add_buffer functions */ | /* end of the add_buffer functions */ | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Read everything until a newline. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| static |  | ||||||
| int GetLine(int sockfd, char *ptr, struct connectdata *conn) |  | ||||||
| { |  | ||||||
|   ssize_t nread; |  | ||||||
|  |  | ||||||
|   /* get us a full line, terminated with a newline */ |  | ||||||
|   for(nread=0; (nread<BUFSIZE); nread++, ptr++) { |  | ||||||
|     if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) || |  | ||||||
|        (nread <= 0) || (*ptr == '\n')) |  | ||||||
|       break; |  | ||||||
|   } |  | ||||||
|   *ptr=0; /* zero terminate */ |  | ||||||
|    |  | ||||||
|   return nread>0?nread:0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * This function checks the linked list of custom HTTP headers for a particular |  * This function checks the linked list of custom HTTP headers for a particular | ||||||
|  * header (prefix). |  * header (prefix). | ||||||
| @@ -257,6 +255,23 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, | |||||||
|   int subversion=0; |   int subversion=0; | ||||||
|   struct SessionHandle *data=conn->data; |   struct SessionHandle *data=conn->data; | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|  |   int res; | ||||||
|  |  | ||||||
|  |   int nread;   /* total size read */ | ||||||
|  |   int perline; /* count bytes per line */ | ||||||
|  |   bool keepon=TRUE; | ||||||
|  |   ssize_t gotbytes; | ||||||
|  |   char *ptr; | ||||||
|  |   int timeout = 3600; /* default timeout in seconds */ | ||||||
|  |   struct timeval interval; | ||||||
|  |   fd_set rkeepfd; | ||||||
|  |   fd_set readfd; | ||||||
|  |   char *line_start; | ||||||
|  |  | ||||||
|  | #define SELECT_OK      0 | ||||||
|  | #define SELECT_ERROR   1 | ||||||
|  | #define SELECT_TIMEOUT 2 | ||||||
|  |   int error = SELECT_OK; | ||||||
|  |  | ||||||
|   infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); |   infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); | ||||||
|  |  | ||||||
| @@ -276,19 +291,109 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, | |||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* wait for the proxy to send us a HTTP/1.0 200 OK header */ |   /* Now, read the full reply we get from the proxy */ | ||||||
|   while(GetLine(tunnelsocket, data->state.buffer, conn)) { |  | ||||||
|     if('\r' == data->state.buffer[0]) |  | ||||||
|       break; /* end of headers */ |  | ||||||
|     if(data->set.verbose) |  | ||||||
|       fprintf(data->set.err, "< %s\n", data->state.buffer); |  | ||||||
|  |  | ||||||
|     if(2 == sscanf(data->state.buffer, "HTTP/1.%d %d", |  | ||||||
|  |   if(data->set.timeout) { | ||||||
|  |     /* if timeout is requested, find out how much remaining time we have */ | ||||||
|  |     timeout = data->set.timeout - /* timeout time */ | ||||||
|  |       Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ | ||||||
|  |     if(timeout <=0 ) { | ||||||
|  |       failf(data, "Transfer aborted due to timeout"); | ||||||
|  |       return -SELECT_TIMEOUT; /* already too little time */ | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   FD_ZERO (&readfd);		/* clear it */ | ||||||
|  |   FD_SET (tunnelsocket, &readfd);     /* read socket */ | ||||||
|  |  | ||||||
|  |   /* get this in a backup variable to be able to restore it on each lap in the | ||||||
|  |      select() loop */ | ||||||
|  |   rkeepfd = readfd; | ||||||
|  |  | ||||||
|  |   ptr=data->state.buffer; | ||||||
|  |   line_start = ptr; | ||||||
|  |  | ||||||
|  |   nread=0; | ||||||
|  |   perline=0; | ||||||
|  |   keepon=TRUE; | ||||||
|  |  | ||||||
|  |   while((nread<BUFSIZE) && (keepon && !error)) { | ||||||
|  |     readfd = rkeepfd;		   /* set every lap */ | ||||||
|  |     interval.tv_sec = timeout; | ||||||
|  |     interval.tv_usec = 0; | ||||||
|  |  | ||||||
|  |     switch (select (tunnelsocket+1, &readfd, NULL, NULL, &interval)) { | ||||||
|  |     case -1: /* select() error, stop reading */ | ||||||
|  |       error = SELECT_ERROR; | ||||||
|  |       failf(data, "Transfer aborted due to select() error"); | ||||||
|  |       break; | ||||||
|  |     case 0: /* timeout */ | ||||||
|  |       error = SELECT_TIMEOUT; | ||||||
|  |       failf(data, "Transfer aborted due to timeout"); | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       /* | ||||||
|  |        * This code previously didn't use the kerberos sec_read() code | ||||||
|  |        * to read, but when we use Curl_read() it may do so. Do confirm | ||||||
|  |        * that this is still ok and then remove this comment! | ||||||
|  |        */ | ||||||
|  |       res= Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, | ||||||
|  |                      &gotbytes); | ||||||
|  |       if(res< 0) | ||||||
|  |         /* EWOULDBLOCK */ | ||||||
|  |         continue; /* go loop yourself */ | ||||||
|  |       else if(res) | ||||||
|  |         keepon = FALSE; | ||||||
|  |       else if(gotbytes <= 0) { | ||||||
|  |         keepon = FALSE; | ||||||
|  |         error = SELECT_ERROR; | ||||||
|  |         failf(data, "Connection aborted"); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         /* we got a whole chunk of data, which can be anything from one | ||||||
|  |          * byte to a set of lines and possibly just a piece of the last | ||||||
|  |          * line */ | ||||||
|  |         int i; | ||||||
|  |  | ||||||
|  |         nread += gotbytes; | ||||||
|  |         for(i = 0; i < gotbytes; ptr++, i++) { | ||||||
|  |           perline++; /* amount of bytes in this line so far */ | ||||||
|  |           if(*ptr=='\n') { | ||||||
|  |             /* a newline is CRLF in ftp-talk, so the CR is ignored as | ||||||
|  |                the line isn't really terminated until the LF comes */ | ||||||
|  |  | ||||||
|  |             /* output debug output if that is requested */ | ||||||
|  |             if(data->set.verbose) { | ||||||
|  |               fputs("< ", data->set.err); | ||||||
|  |               fwrite(line_start, perline, 1, data->set.err); | ||||||
|  |               /* no need to output LF here, it is part of the data */ | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if('\r' == line_start[0]) { | ||||||
|  |               /* end of headers */ | ||||||
|  |               keepon=FALSE; | ||||||
|  |               break; /* breaks out of loop, not switch */ | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(2 == sscanf(line_start, "HTTP/1.%d %d", | ||||||
|                            &subversion, |                            &subversion, | ||||||
|                            &httperror)) { |                            &httperror)) { | ||||||
|               ; |               ; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             perline=0; /* line starts over here */ | ||||||
|  |             line_start = ptr+1; | ||||||
|           } |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } /* switch */ | ||||||
|  |   } /* while there's buffer left and loop is requested */ | ||||||
|  |  | ||||||
|  |   if(error) | ||||||
|  |     return CURLE_READ_ERROR; | ||||||
|  |  | ||||||
|   if(200 != httperror) { |   if(200 != httperror) { | ||||||
|     if(407 == httperror) |     if(407 == httperror) | ||||||
|       /* Added Nov 6 1998 */ |       /* Added Nov 6 1998 */ | ||||||
| @@ -318,15 +423,18 @@ CURLcode Curl_http_connect(struct connectdata *conn) | |||||||
|    * us to the host we want to talk to.  Only after the connect |    * us to the host we want to talk to.  Only after the connect | ||||||
|    * has occured, can we start talking SSL |    * has occured, can we start talking SSL | ||||||
|    */ |    */ | ||||||
|   if (conn->protocol & PROT_HTTPS) { |  | ||||||
|     if (data->change.proxy) { |   if(data->change.proxy && | ||||||
|       /* HTTPS through a proxy can only be done with a tunnel */ |      ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { | ||||||
|  |  | ||||||
|  |     /* either HTTPS over proxy, OR explicitly asked for a tunnel */ | ||||||
|     result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, |     result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket, | ||||||
|                                          conn->hostname, conn->remote_port); |                                          conn->hostname, conn->remote_port); | ||||||
|     if(CURLE_OK != result) |     if(CURLE_OK != result) | ||||||
|       return result; |       return result; | ||||||
|   }     |   }     | ||||||
|  |  | ||||||
|  |   if(conn->protocol & PROT_HTTPS) { | ||||||
|     /* now, perform the SSL initialization for this socket */ |     /* now, perform the SSL initialization for this socket */ | ||||||
|     result = Curl_SSLConnect(conn); |     result = Curl_SSLConnect(conn); | ||||||
|     if(result) |     if(result) | ||||||
| @@ -366,7 +474,7 @@ CURLcode Curl_http_done(struct connectdata *conn) | |||||||
|   if(0 == (http->readbytecount + conn->headerbytecount)) { |   if(0 == (http->readbytecount + conn->headerbytecount)) { | ||||||
|     /* nothing was read from the HTTP server, this can't be right |     /* nothing was read from the HTTP server, this can't be right | ||||||
|        so we return an error here */ |        so we return an error here */ | ||||||
|     failf(data, "Empty reply from server\n"); |     failf(data, "Empty reply from server"); | ||||||
|     return CURLE_GOT_NOTHING; |     return CURLE_GOT_NOTHING; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -450,7 +558,9 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|                              host, ppath, |                              host, ppath, | ||||||
|                              conn->protocol&PROT_HTTPS?TRUE:FALSE); |                              conn->protocol&PROT_HTTPS?TRUE:FALSE); | ||||||
|   } |   } | ||||||
|   if ((data->change.proxy) && !(conn->protocol&PROT_HTTPS))  { |   if (data->change.proxy && | ||||||
|  |       !data->set.tunnel_thru_httpproxy && | ||||||
|  |       !(conn->protocol&PROT_HTTPS))  { | ||||||
|     /* The path sent to the proxy is in fact the entire URL */ |     /* The path sent to the proxy is in fact the entire URL */ | ||||||
|     ppath = data->change.url; |     ppath = data->change.url; | ||||||
|   } |   } | ||||||
| @@ -525,7 +635,7 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|  |  | ||||||
|         passed += actuallyread; |         passed += actuallyread; | ||||||
|         if(actuallyread != readthisamountnow) { |         if(actuallyread != readthisamountnow) { | ||||||
|           failf(data, "Could only read %d bytes from the input\n", |           failf(data, "Could only read %d bytes from the input", | ||||||
|                 passed); |                 passed); | ||||||
|           return CURLE_READ_ERROR; |           return CURLE_READ_ERROR; | ||||||
|         } |         } | ||||||
| @@ -536,7 +646,7 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|         data->set.infilesize -= conn->resume_from; |         data->set.infilesize -= conn->resume_from; | ||||||
|  |  | ||||||
|         if(data->set.infilesize <= 0) { |         if(data->set.infilesize <= 0) { | ||||||
|           failf(data, "File already completely uploaded\n"); |           failf(data, "File already completely uploaded"); | ||||||
|           return CURLE_PARTIAL_FILE; |           return CURLE_PARTIAL_FILE; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @@ -650,10 +760,8 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|        * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). |        * equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616). | ||||||
|        */ |        */ | ||||||
|  |  | ||||||
| #ifdef HAVE_LOCALTIME_R | #ifdef HAVE_GMTIME_R | ||||||
|       /* thread-safe version */ |       /* thread-safe version */ | ||||||
|       /* We assume that the presense of localtime_r() proves the presense |  | ||||||
|          of gmtime_r() which is a bit ugly but might work */ |  | ||||||
|       struct tm keeptime; |       struct tm keeptime; | ||||||
|       thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); |       thistime = (struct tm *)gmtime_r(&data->set.timevalue, &keeptime); | ||||||
| #else | #else | ||||||
| @@ -666,7 +774,7 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|  |  | ||||||
| #ifdef HAVE_STRFTIME | #ifdef HAVE_STRFTIME | ||||||
|       /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ |       /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ | ||||||
|       strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S %Z", thistime); |       strftime(buf, BUFSIZE-1, "%a, %d %b %Y %H:%M:%S GMT", thistime); | ||||||
| #else | #else | ||||||
|       /* TODO: Right, we *could* write a replacement here */ |       /* TODO: Right, we *could* write a replacement here */ | ||||||
|       strcpy(buf, "no strftime() support"); |       strcpy(buf, "no strftime() support"); | ||||||
| @@ -707,10 +815,8 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(HTTPREQ_POST_FORM == data->set.httpreq) { |     if(HTTPREQ_POST_FORM == data->set.httpreq) { | ||||||
|       char contentType[256]; |  | ||||||
|       int linelength=0; |  | ||||||
|       if(Curl_FormInit(&http->form, http->sendit)) { |       if(Curl_FormInit(&http->form, http->sendit)) { | ||||||
|         failf(data, "Internal HTTP POST error!\n"); |         failf(data, "Internal HTTP POST error!"); | ||||||
|         return CURLE_HTTP_POST_ERROR; |         return CURLE_HTTP_POST_ERROR; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -723,7 +829,7 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|       data->set.in = (FILE *)&http->form; |       data->set.in = (FILE *)&http->form; | ||||||
|  |  | ||||||
|       add_bufferf(req_buffer, |       add_bufferf(req_buffer, | ||||||
|                   "Content-Length: %d\r\n", http->postsize-2); |                   "Content-Length: %d\r\n", http->postsize); | ||||||
|  |  | ||||||
|       if(!checkheaders(data, "Expect:")) { |       if(!checkheaders(data, "Expect:")) { | ||||||
|         /* if not disabled explicitly we add a Expect: 100-continue |         /* if not disabled explicitly we add a Expect: 100-continue | ||||||
| @@ -732,21 +838,33 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|         add_bufferf(req_buffer, |         add_bufferf(req_buffer, | ||||||
|                     "Expect: 100-continue\r\n"); |                     "Expect: 100-continue\r\n"); | ||||||
|         data->set.expect100header = TRUE; |         data->set.expect100header = TRUE; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if(!checkheaders(data, "Content-Type:")) { | ||||||
|         /* Get Content-Type: line from Curl_FormReadOneLine, which happens |         /* Get Content-Type: line from Curl_FormReadOneLine, which happens | ||||||
|            to always be the first line. We can know this for sure since |            to always be the first line. We can know this for sure since | ||||||
|            we always build the formpost linked list the same way! */ |            we always build the formpost linked list the same way! | ||||||
|  |  | ||||||
|  |            The Content-Type header line also contains the MIME boundary | ||||||
|  |            string etc why disabling this header is likely to not make things | ||||||
|  |            work, but we support it anyway. | ||||||
|  |         */ | ||||||
|  |         char contentType[256]; | ||||||
|  |         int linelength=0; | ||||||
|         linelength = Curl_FormReadOneLine (contentType, |         linelength = Curl_FormReadOneLine (contentType, | ||||||
|                                            sizeof(contentType), |                                            sizeof(contentType), | ||||||
|                                            1, |                                            1, | ||||||
|                                            (FILE *)&http->form); |                                            (FILE *)&http->form); | ||||||
|         if(linelength == -1) { |         if(linelength == -1) { | ||||||
|           failf(data, "Could not get Content-Type header line!\n"); |           failf(data, "Could not get Content-Type header line!"); | ||||||
|           return CURLE_HTTP_POST_ERROR; |           return CURLE_HTTP_POST_ERROR; | ||||||
|         } |         } | ||||||
|         add_buffer(req_buffer, contentType, linelength); |         add_buffer(req_buffer, contentType, linelength); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       /* make the request end in a true CRLF */ | ||||||
|  |       add_buffer(req_buffer, "\r\n", 2); | ||||||
|  |  | ||||||
|       /* set upload size to the progress meter */ |       /* set upload size to the progress meter */ | ||||||
|       Curl_pgrsSetUploadSize(data, http->postsize); |       Curl_pgrsSetUploadSize(data, http->postsize); | ||||||
|  |  | ||||||
| @@ -827,12 +945,11 @@ CURLcode Curl_http(struct connectdata *conn) | |||||||
|           add_buffer(req_buffer, "\r\n", 2); |           add_buffer(req_buffer, "\r\n", 2); | ||||||
|           add_buffer(req_buffer, data->set.postfields, |           add_buffer(req_buffer, data->set.postfields, | ||||||
|                      data->set.postfieldsize); |                      data->set.postfieldsize); | ||||||
|           add_buffer(req_buffer, "\r\n", 2); |  | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           add_bufferf(req_buffer, |           add_bufferf(req_buffer, | ||||||
|                       "\r\n" |                       "\r\n" | ||||||
|                       "%s\r\n", |                       "%s", | ||||||
|                       data->set.postfields ); |                       data->set.postfields ); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|   | |||||||
							
								
								
									
										59
									
								
								lib/krb4.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								lib/krb4.c
									
									
									
									
									
								
							| @@ -57,6 +57,10 @@ | |||||||
| #include "ftp.h" | #include "ftp.h" | ||||||
| #include "sendf.h" | #include "sendf.h" | ||||||
|  |  | ||||||
|  | #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) | ||||||
|  | #include "inet_ntoa_r.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* The last #include file should be: */ | /* The last #include file should be: */ | ||||||
| #ifdef MALLOCDEBUG | #ifdef MALLOCDEBUG | ||||||
| #include "memdebug.h" | #include "memdebug.h" | ||||||
| @@ -193,10 +197,10 @@ krb4_auth(void *app_data, struct connectdata *conn) | |||||||
|   int checksum; |   int checksum; | ||||||
|   u_int32_t cs; |   u_int32_t cs; | ||||||
|   struct krb4_data *d = app_data; |   struct krb4_data *d = app_data; | ||||||
|   struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR; |  | ||||||
|   char *host = conn->hostaddr->h_name; |   char *host = conn->hostaddr->h_name; | ||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
|   int l = sizeof(conn->local_addr); |   int l = sizeof(conn->local_addr); | ||||||
|  |   struct SessionHandle *data = conn->data; | ||||||
|  |  | ||||||
|   if(getsockname(conn->firstsocket, |   if(getsockname(conn->firstsocket, | ||||||
|                  (struct sockaddr *)LOCAL_ADDR, &l) < 0) |                  (struct sockaddr *)LOCAL_ADDR, &l) < 0) | ||||||
| @@ -207,66 +211,62 @@ krb4_auth(void *app_data, struct connectdata *conn) | |||||||
|   if(ret == KDC_PR_UNKNOWN) |   if(ret == KDC_PR_UNKNOWN) | ||||||
|     ret = mk_auth(d, &adat, "rcmd", host, checksum); |     ret = mk_auth(d, &adat, "rcmd", host, checksum); | ||||||
|   if(ret) { |   if(ret) { | ||||||
|     printf("%s\n", krb_get_err_text(ret)); |     Curl_infof(data, "%s\n", krb_get_err_text(ret)); | ||||||
|     return AUTH_CONTINUE; |     return AUTH_CONTINUE; | ||||||
|   } |   } | ||||||
|    |    | ||||||
| #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM | #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM | ||||||
|   if (krb_get_config_bool("nat_in_use")) { |   if (krb_get_config_bool("nat_in_use")) { | ||||||
|  |     struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR; | ||||||
|     struct in_addr natAddr; |     struct in_addr natAddr; | ||||||
|  |  | ||||||
|     if (krb_get_our_ip_for_realm(krb_realmofhost(host), |     if (krb_get_our_ip_for_realm(krb_realmofhost(host), | ||||||
|                                  &natAddr) != KSUCCESS |                                  &natAddr) != KSUCCESS | ||||||
|         && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) |         && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) | ||||||
|       printf("Can't get address for realm %s\n", |       Curl_infof(data, "Can't get address for realm %s\n", | ||||||
|                  krb_realmofhost(host)); |                  krb_realmofhost(host)); | ||||||
|     else { |     else { | ||||||
|       if (natAddr.s_addr != localaddr->sin_addr.s_addr) { |       if (natAddr.s_addr != localaddr->sin_addr.s_addr) { | ||||||
|         printf("Using NAT IP address (%s) for kerberos 4\n", | #ifdef HAVE_INET_NTOA_R | ||||||
|                (char *)inet_ntoa(natAddr)); |         char ntoa_buf[64]; | ||||||
|  |         char *ip = (char *)inet_ntoa_r(natAddr, ntoa_buf, sizeof(ntoa_buf)); | ||||||
|  | #else | ||||||
|  |         char *ip = (char *)inet_ntoa(natAddr); | ||||||
|  | #endif | ||||||
|  |         Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip); | ||||||
|         localaddr->sin_addr = natAddr; |         localaddr->sin_addr = natAddr; | ||||||
|          |  | ||||||
|         /* |  | ||||||
|          * This not the best place to do this, but it is here we know that |  | ||||||
|          * (probably) NAT is in use!  */ |  | ||||||
|  |  | ||||||
|         /*passivemode = 1;***/ |  | ||||||
|         /*printf("Setting: Passive mode on.\n");***/ |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   /*printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));***/ |  | ||||||
|   /*printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));***/ |  | ||||||
|  |  | ||||||
|   if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) { |   if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) { | ||||||
|     printf("Out of memory base64-encoding.\n"); |     Curl_failf(data, "Out of memory base64-encoding"); | ||||||
|     return AUTH_CONTINUE; |     return AUTH_CONTINUE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(Curl_ftpsendf(conn, "ADAT %s", p)) |   if(Curl_ftpsendf(conn, "ADAT %s", p)) | ||||||
|     return -2; |     return -2; | ||||||
|  |  | ||||||
|   nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL); |   nread = Curl_GetFTPResponse(data->state.buffer, conn, NULL); | ||||||
|   if(nread < 0) |   if(nread < 0) | ||||||
|     return -1; |     return -1; | ||||||
|   free(p); |   free(p); | ||||||
|  |  | ||||||
|   if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){ |   if(data->state.buffer[0] != '2'){ | ||||||
|     printf("Server didn't accept auth data.\n"); |     Curl_failf(data, "Server didn't accept auth data"); | ||||||
|     return AUTH_ERROR; |     return AUTH_ERROR; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   p = strstr(conn->data->state.buffer, "ADAT="); |   p = strstr(data->state.buffer, "ADAT="); | ||||||
|   if(!p) { |   if(!p) { | ||||||
|     printf("Remote host didn't send adat reply.\n"); |     Curl_failf(data, "Remote host didn't send adat reply"); | ||||||
|     return AUTH_ERROR; |     return AUTH_ERROR; | ||||||
|   } |   } | ||||||
|   p += 5; |   p += 5; | ||||||
|   len = Curl_base64_decode(p, adat.dat); |   len = Curl_base64_decode(p, adat.dat); | ||||||
|   if(len < 0) { |   if(len < 0) { | ||||||
|     printf("Failed to decode base64 from server.\n"); |     Curl_failf(data, "Failed to decode base64 from server"); | ||||||
|     return AUTH_ERROR; |     return AUTH_ERROR; | ||||||
|   } |   } | ||||||
|   adat.length = len; |   adat.length = len; | ||||||
| @@ -274,13 +274,13 @@ krb4_auth(void *app_data, struct connectdata *conn) | |||||||
|                     (struct sockaddr_in *)hisctladdr,  |                     (struct sockaddr_in *)hisctladdr,  | ||||||
|                     (struct sockaddr_in *)myctladdr, &msg_data); |                     (struct sockaddr_in *)myctladdr, &msg_data); | ||||||
|   if(ret) { |   if(ret) { | ||||||
|     printf("Error reading reply from server: %s.\n",  |     Curl_failf(data, "Error reading reply from server: %s",  | ||||||
|                krb_get_err_text(ret)); |                krb_get_err_text(ret)); | ||||||
|     return AUTH_ERROR; |     return AUTH_ERROR; | ||||||
|   } |   } | ||||||
|   krb_get_int(msg_data.app_data, &cs, 4, 0); |   krb_get_int(msg_data.app_data, &cs, 4, 0); | ||||||
|   if(cs - checksum != 1) { |   if(cs - checksum != 1) { | ||||||
|     printf("Bad checksum returned from server.\n"); |     Curl_failf(data, "Bad checksum returned from server"); | ||||||
|     return AUTH_ERROR; |     return AUTH_ERROR; | ||||||
|   } |   } | ||||||
|   return AUTH_OK; |   return AUTH_OK; | ||||||
| @@ -321,15 +321,14 @@ void Curl_krb_kauth(struct connectdata *conn) | |||||||
|   if(nread < 0) |   if(nread < 0) | ||||||
|     return /*CURLE_OPERATION_TIMEOUTED*/; |     return /*CURLE_OPERATION_TIMEOUTED*/; | ||||||
|  |  | ||||||
|   if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){ |   if(conn->data->state.buffer[0] != '3'){ | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     /*code = -1;***/ |  | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   p = strstr(conn->data->state.buffer, "T="); |   p = strstr(conn->data->state.buffer, "T="); | ||||||
|   if(!p) { |   if(!p) { | ||||||
|     printf("Bad reply from server.\n"); |     Curl_failf(conn->data, "Bad reply from server"); | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -337,7 +336,7 @@ void Curl_krb_kauth(struct connectdata *conn) | |||||||
|   p += 2; |   p += 2; | ||||||
|   tmp = Curl_base64_decode(p, &tkt.dat); |   tmp = Curl_base64_decode(p, &tkt.dat); | ||||||
|   if(tmp < 0) { |   if(tmp < 0) { | ||||||
|     printf("Failed to decode base64 in reply.\n"); |     Curl_failf(conn->data, "Failed to decode base64 in reply.\n"); | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -346,7 +345,7 @@ void Curl_krb_kauth(struct connectdata *conn) | |||||||
|      |      | ||||||
|   p = strstr(conn->data->state.buffer, "P="); |   p = strstr(conn->data->state.buffer, "P="); | ||||||
|   if(!p) { |   if(!p) { | ||||||
|     printf("Bad reply from server.\n"); |     Curl_failf(conn->data, "Bad reply from server"); | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -374,7 +373,7 @@ void Curl_krb_kauth(struct connectdata *conn) | |||||||
|   memset(schedule, 0, sizeof(schedule)); |   memset(schedule, 0, sizeof(schedule)); | ||||||
|   memset(passwd, 0, sizeof(passwd)); |   memset(passwd, 0, sizeof(passwd)); | ||||||
|   if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) { |   if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) { | ||||||
|     failf(conn->data, "Out of memory base64-encoding.\n"); |     failf(conn->data, "Out of memory base64-encoding."); | ||||||
|     Curl_set_command_prot(conn, save); |     Curl_set_command_prot(conn, save); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -95,9 +95,11 @@ static void DynaClose(void) | |||||||
| #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) | #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) | ||||||
|   if (libldap) { |   if (libldap) { | ||||||
|     dlclose(libldap); |     dlclose(libldap); | ||||||
|  |     libldap=NULL; | ||||||
|   } |   } | ||||||
|   if (liblber) { |   if (liblber) { | ||||||
|     dlclose(liblber); |     dlclose(liblber); | ||||||
|  |     liblber=NULL; | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -174,7 +176,9 @@ CURLcode Curl_ldap(struct connectdata *conn) | |||||||
| 	  conn->hostname, conn->port); | 	  conn->hostname, conn->port); | ||||||
|     status = CURLE_COULDNT_CONNECT; |     status = CURLE_COULDNT_CONNECT; | ||||||
|   } else { |   } else { | ||||||
|     rc = ldap_simple_bind_s(server, data->state.user, data->state.passwd); |     rc = ldap_simple_bind_s(server, | ||||||
|  |                             conn->bits.user_passwd?data->state.user:NULL, | ||||||
|  |                             conn->bits.user_passwd?data->state.passwd:NULL); | ||||||
|     if (rc != 0) { |     if (rc != 0) { | ||||||
|       failf(data, "LDAP: %s", ldap_err2string(rc)); |       failf(data, "LDAP: %s", ldap_err2string(rc)); | ||||||
|       status = CURLE_LDAP_CANNOT_BIND; |       status = CURLE_LDAP_CANNOT_BIND; | ||||||
|   | |||||||
							
								
								
									
										168
									
								
								lib/llist.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								lib/llist.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #include "llist.h" | ||||||
|  |  | ||||||
|  | #ifdef MALLOCDEBUG | ||||||
|  | /* this must be the last include file */ | ||||||
|  | #include "memdebug.h" | ||||||
|  | #endif | ||||||
|  | void  | ||||||
|  | curl_llist_init(curl_llist *l, curl_llist_dtor dtor) | ||||||
|  | { | ||||||
|  |   l->size = 0; | ||||||
|  |   l->dtor = dtor; | ||||||
|  |   l->head = NULL; | ||||||
|  |   l->tail = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | curl_llist * | ||||||
|  | curl_llist_alloc(curl_llist_dtor dtor) | ||||||
|  | { | ||||||
|  |   curl_llist *list; | ||||||
|  |  | ||||||
|  |   list = (curl_llist *)malloc(sizeof(curl_llist)); | ||||||
|  |   if(NULL == list) | ||||||
|  |     return NULL; | ||||||
|  |  | ||||||
|  |   curl_llist_init(list, dtor); | ||||||
|  |  | ||||||
|  |   return list; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p) | ||||||
|  | { | ||||||
|  |   curl_llist_element  *ne; | ||||||
|  |  | ||||||
|  |   ne = (curl_llist_element *) malloc(sizeof(curl_llist_element)); | ||||||
|  |   ne->ptr = (void *) p; | ||||||
|  |   if (list->size == 0) { | ||||||
|  |     list->head = ne; | ||||||
|  |     list->head->prev = NULL; | ||||||
|  |     list->head->next = NULL; | ||||||
|  |     list->tail = ne; | ||||||
|  |   } else { | ||||||
|  |     ne->next = e->next; | ||||||
|  |     ne->prev = e; | ||||||
|  |     if (e->next) { | ||||||
|  |       e->next->prev = ne; | ||||||
|  |     } else { | ||||||
|  |       list->tail = ne; | ||||||
|  |     } | ||||||
|  |     e->next = ne; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ++list->size; | ||||||
|  |  | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p) | ||||||
|  | { | ||||||
|  |   curl_llist_element *ne; | ||||||
|  |  | ||||||
|  |   ne = (curl_llist_element *) malloc(sizeof(curl_llist_element)); | ||||||
|  |   ne->ptr = (void *) p; | ||||||
|  |   if (list->size == 0) { | ||||||
|  |     list->head = ne; | ||||||
|  |     list->head->prev = NULL; | ||||||
|  |     list->head->next = NULL; | ||||||
|  |     list->tail = ne; | ||||||
|  |   } else { | ||||||
|  |     ne->next = e; | ||||||
|  |     ne->prev = e->prev; | ||||||
|  |     if (e->prev) | ||||||
|  |       e->prev->next = ne; | ||||||
|  |     else | ||||||
|  |       list->head = ne; | ||||||
|  |     e->prev = ne; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ++list->size; | ||||||
|  |  | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) | ||||||
|  | { | ||||||
|  |   if (e == NULL || list->size == 0) | ||||||
|  |     return 1; | ||||||
|  |  | ||||||
|  |   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->dtor(user, e->ptr); | ||||||
|  |   free(e); | ||||||
|  |   --list->size; | ||||||
|  |  | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user) | ||||||
|  | { | ||||||
|  |   return curl_llist_remove(list, e->next, user); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int  | ||||||
|  | curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user) | ||||||
|  | { | ||||||
|  |   return curl_llist_remove(list, e->prev, user); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t  | ||||||
|  | curl_llist_count(curl_llist *list) | ||||||
|  | { | ||||||
|  |   return list->size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void  | ||||||
|  | curl_llist_destroy(curl_llist *list, void *user) | ||||||
|  | { | ||||||
|  |   while (list->size > 0) { | ||||||
|  |     curl_llist_remove(list, CURL_LLIST_TAIL(list), user); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   free(list); | ||||||
|  |   list = NULL; | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								lib/llist.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/llist.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #ifndef __LLIST_H | ||||||
|  | #define __LLIST_H | ||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | typedef void (*curl_llist_dtor)(void *, void *); | ||||||
|  |  | ||||||
|  | typedef struct _curl_llist_element { | ||||||
|  |   void *ptr; | ||||||
|  |  | ||||||
|  |   struct _curl_llist_element *prev; | ||||||
|  |   struct _curl_llist_element *next; | ||||||
|  | } curl_llist_element; | ||||||
|  |  | ||||||
|  | typedef struct _curl_llist { | ||||||
|  |   curl_llist_element *head; | ||||||
|  |   curl_llist_element *tail; | ||||||
|  |  | ||||||
|  |   curl_llist_dtor dtor; | ||||||
|  |  | ||||||
|  |   size_t size; | ||||||
|  | } curl_llist; | ||||||
|  |  | ||||||
|  | void curl_llist_init(curl_llist *, curl_llist_dtor); | ||||||
|  | curl_llist *curl_llist_alloc(curl_llist_dtor); | ||||||
|  | int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *); | ||||||
|  | int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *); | ||||||
|  | int curl_llist_remove(curl_llist *, curl_llist_element *, void *); | ||||||
|  | int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *); | ||||||
|  | size_t curl_llist_count(curl_llist *); | ||||||
|  | void curl_llist_destroy(curl_llist *, void *); | ||||||
|  |  | ||||||
|  | #define CURL_LLIST_HEAD(__l) ((__l)->head) | ||||||
|  | #define CURL_LLIST_TAIL(__l) ((__l)->tail) | ||||||
|  | #define CURL_LLIST_NEXT(__e) ((__e)->next) | ||||||
|  | #define CURL_LLIST_PREV(__e) ((__e)->prev) | ||||||
|  | #define CURL_LLIST_VALP(__e) ((__e)->ptr) | ||||||
|  | #define CURL_LLIST_IS_TAIL(__e) ((__e)->next ? 0 : 1) | ||||||
|  | #define CURL_LLIST_IS_HEAD(__e) ((__e)->prev ? 0 : 1) | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -70,6 +70,9 @@ void curl_memdebug(const char *logname) | |||||||
| void *curl_domalloc(size_t size, int line, const char *source) | void *curl_domalloc(size_t size, int line, const char *source) | ||||||
| { | { | ||||||
|   void *mem=(malloc)(size); |   void *mem=(malloc)(size); | ||||||
|  |   if(mem) | ||||||
|  |     /* fill memory with junk */ | ||||||
|  |     memset(mem, 0xA5, size); | ||||||
|   if(logfile) |   if(logfile) | ||||||
|     fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n", |     fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n", | ||||||
|             source, line, size, mem); |             source, line, size, mem); | ||||||
| @@ -165,7 +168,10 @@ int curl_fclose(FILE *file, int line, const char *source) | |||||||
|             source, line, file); |             source, line, file); | ||||||
|   return res; |   return res; | ||||||
| } | } | ||||||
|  | #else | ||||||
|  | #ifdef VMS | ||||||
|  | int VOID_VAR_MEMDEBUG;	 | ||||||
|  | #endif | ||||||
| #endif /* MALLOCDEBUG */ | #endif /* MALLOCDEBUG */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -1,6 +1,14 @@ | |||||||
| #ifdef MALLOCDEBUG | #ifdef MALLOCDEBUG | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SYS_TYPES_H | ||||||
|  | #include <sys/types.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SYS_SOCKET_H | ||||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||||
|  | #endif | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #ifdef HAVE_MEMORY_H | #ifdef HAVE_MEMORY_H | ||||||
| #include <memory.h> | #include <memory.h> | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								lib/mprintf.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								lib/mprintf.c
									
									
									
									
									
								
							| @@ -24,82 +24,13 @@ | |||||||
|  * - Max 128 parameters |  * - Max 128 parameters | ||||||
|  * - No 'long double' support. |  * - No 'long double' support. | ||||||
|  * |  * | ||||||
|  ************************************************************************* |  * If you ever want truly portable and good *printf() clones, the project that | ||||||
|  * |  * took on from here is named 'Trio' and you find more details on the trio web | ||||||
|  * |  * page at http://daniel.haxx.se/trio/ | ||||||
|  * 1998/01/10  (v2.8) |  | ||||||
|  *   Daniel |  | ||||||
|  *   - Updated version number. |  | ||||||
|  *   - Corrected a static non-zero prefixed width problem. |  | ||||||
|  * |  | ||||||
|  * 1998/11/17 - Daniel |  | ||||||
|  *   Added daprintf() and dvaprintf() for allocated printf() and vprintf(). |  | ||||||
|  *   They return an allocated buffer with the result inside. The result must |  | ||||||
|  *   be free()ed! |  | ||||||
|  * |  | ||||||
|  * 1998/08/23 - breese |  | ||||||
|  * |  | ||||||
|  *   Converted all non-printable (and non-whitespace) characters into |  | ||||||
|  *   their decimal ASCII value preceeded by a '\' character |  | ||||||
|  *   (this only applies to snprintf family so far) |  | ||||||
|  * |  | ||||||
|  *   Added %S (which is the same as %#s) |  | ||||||
|  * |  | ||||||
|  * 1998/05/05 (v2.7) |  | ||||||
|  * |  | ||||||
|  *   Fixed precision and width qualifiers (%.*s) |  | ||||||
|  * |  | ||||||
|  *   Added support for snprintf() |  | ||||||
|  * |  | ||||||
|  *   Quoting (%#s) is disabled for the (nil) pointer |  | ||||||
|  * |  | ||||||
|  * 1997/06/09 (v2.6) |  | ||||||
|  * |  | ||||||
|  *   %#s means that the string will be quoted with " |  | ||||||
|  *   (I was getting tired of writing \"%s\" all the time) |  | ||||||
|  * |  | ||||||
|  *   [ERR] for strings changed to (nil) |  | ||||||
|  * |  | ||||||
|  * v2.5 |  | ||||||
|  * - Added C++ support |  | ||||||
|  * - Prepended all internal functions with dprintf_ |  | ||||||
|  * - Defined the booleans |  | ||||||
|  * |  | ||||||
|  * v2.4 |  | ||||||
|  * - Added dvsprintf(), dvfprintf() and dvprintf(). |  | ||||||
|  * - Made the formatting function available with the name _formatf() to enable |  | ||||||
|  *   other *printf()-inspired functions. (I considered adding a dmsprintf() |  | ||||||
|  *   that works like sprintf() but allocates the destination string and |  | ||||||
|  *   possibly enlarges it itself, but things like that should be done with the |  | ||||||
|  *   new _formatf() instead.) |  | ||||||
|  * |  | ||||||
|  * v2.3 |  | ||||||
|  * - Small modifications to make it compile nicely at both Daniel's and |  | ||||||
|  *   Bjorn's place. |  | ||||||
|  * |  | ||||||
|  * v2.2 |  | ||||||
|  * - Made it work with text to the right of the last %! |  | ||||||
|  * - Introduced dprintf(), dsprintf() and dfprintf(). |  | ||||||
|  * - Float/double support enabled. This system is currently using the ordinary |  | ||||||
|  *   sprintf() function. NOTE that positional parameters, widths and precisions |  | ||||||
|  *   will still work like it should since the d-system takes care of that and |  | ||||||
|  *   passes that information re-formatted to the old sprintf(). |  | ||||||
|  * |  | ||||||
|  * v2.1 |  | ||||||
|  * - Fixed space padding (i.e %d was extra padded previously) |  | ||||||
|  * - long long output is supported |  | ||||||
|  * - alternate output is done correct like in %#08x |  | ||||||
|  * |  | ||||||
|  ****************************************************************************/ |  | ||||||
|  |  | ||||||
| static const char rcsid[] = "@(#)$Id$"; |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * To test: |  | ||||||
|  * |  | ||||||
|  * Use WIDTH, PRECISION and NUMBERED ARGUMENT combined. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| @@ -107,6 +38,15 @@ static const char rcsid[] = "@(#)$Id$"; | |||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  | #ifndef SIZEOF_LONG_LONG | ||||||
|  | /* prevents warnings on picky compilers */ | ||||||
|  | #define SIZEOF_LONG_LONG 0 | ||||||
|  | #endif | ||||||
|  | #ifndef SIZEOF_LONG_DOUBLE | ||||||
|  | #define SIZEOF_LONG_DOUBLE 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /* The last #include file should be: */ | /* The last #include file should be: */ | ||||||
| #ifdef MALLOCDEBUG | #ifdef MALLOCDEBUG | ||||||
| #include "memdebug.h" | #include "memdebug.h" | ||||||
| @@ -759,9 +699,8 @@ static int dprintf_formatf( | |||||||
| #if SIZEOF_LONG_LONG | #if SIZEOF_LONG_LONG | ||||||
|       if(p->flags & FLAGS_LONGLONG) { |       if(p->flags & FLAGS_LONGLONG) { | ||||||
| 	 /* long long */ | 	 /* long long */ | ||||||
| 	num = p->data.lnum; | 	is_neg = p->data.lnum < 0; | ||||||
| 	is_neg = num < 0; | 	num = is_neg ? (- p->data.lnum) : p->data.lnum; | ||||||
| 	num = is_neg ? (- num) : num; |  | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
| #endif | #endif | ||||||
| @@ -909,14 +848,14 @@ static int dprintf_formatf( | |||||||
| 	} | 	} | ||||||
| 	else { | 	else { | ||||||
| 	  /* Write "(nil)" for a nil pointer.  */ | 	  /* Write "(nil)" for a nil pointer.  */ | ||||||
| 	  static char nil[] = "(nil)"; | 	  static char strnil[] = "(nil)"; | ||||||
| 	  register char *point; | 	  register char *point; | ||||||
| 	   | 	   | ||||||
| 	  width -= sizeof(nil) - 1; | 	  width -= sizeof(strnil) - 1; | ||||||
| 	  if (p->flags & FLAGS_LEFT) | 	  if (p->flags & FLAGS_LEFT) | ||||||
| 	    while (width-- > 0) | 	    while (width-- > 0) | ||||||
| 	      OUTCHAR(' '); | 	      OUTCHAR(' '); | ||||||
| 	  for (point = nil; *point != '\0'; ++point) | 	  for (point = strnil; *point != '\0'; ++point) | ||||||
| 	    OUTCHAR(*point); | 	    OUTCHAR(*point); | ||||||
| 	  if (! (p->flags & FLAGS_LEFT)) | 	  if (! (p->flags & FLAGS_LEFT)) | ||||||
| 	    while (width-- > 0) | 	    while (width-- > 0) | ||||||
| @@ -1198,7 +1137,7 @@ int main() | |||||||
| { | { | ||||||
|   char buffer[129]; |   char buffer[129]; | ||||||
|   char *ptr; |   char *ptr; | ||||||
| #ifdef SIZEOF_LONG_LONG | #if SIZEOF_LONG_LONG>0 | ||||||
|   long long hullo; |   long long hullo; | ||||||
|   dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65); |   dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65); | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										361
									
								
								lib/multi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										361
									
								
								lib/multi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,361 @@ | |||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "setup.h" | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | #include "multi.h" /* will become <curl/multi.h> soon */ | ||||||
|  |  | ||||||
|  | #include "urldata.h" | ||||||
|  | #include "transfer.h" | ||||||
|  | #include "url.h" | ||||||
|  |  | ||||||
|  | struct Curl_message { | ||||||
|  |   /* the 'CURLMsg' is the part that is visible to the external user */ | ||||||
|  |   struct CURLMsg extmsg; | ||||||
|  |   struct Curl_message *next; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |   CURLM_STATE_INIT, | ||||||
|  |   CURLM_STATE_CONNECT, | ||||||
|  |   CURLM_STATE_DO, | ||||||
|  |   CURLM_STATE_PERFORM, | ||||||
|  |   CURLM_STATE_DONE, | ||||||
|  |   CURLM_STATE_COMPLETED, | ||||||
|  |  | ||||||
|  |   CURLM_STATE_LAST /* not a true state, never use this */ | ||||||
|  | } CURLMstate; | ||||||
|  |  | ||||||
|  | struct Curl_one_easy { | ||||||
|  |   /* first, two fields for the linked list of these */ | ||||||
|  |   struct Curl_one_easy *next; | ||||||
|  |   struct Curl_one_easy *prev; | ||||||
|  |    | ||||||
|  |   struct SessionHandle *easy_handle; /* the easy handle for this unit */ | ||||||
|  |   struct connectdata *easy_conn;     /* the "unit's" connection */ | ||||||
|  |  | ||||||
|  |   CURLMstate state;  /* the handle's state */ | ||||||
|  |   CURLcode result;   /* previous result */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define CURL_MULTI_HANDLE 0x000bab1e | ||||||
|  |  | ||||||
|  | #define GOOD_MULTI_HANDLE(x) ((x)&&(((struct Curl_multi *)x)->type == CURL_MULTI_HANDLE)) | ||||||
|  | #define GOOD_EASY_HANDLE(x) (x) | ||||||
|  |  | ||||||
|  | /* This is the struct known as CURLM on the outside */ | ||||||
|  | struct Curl_multi { | ||||||
|  |   /* First a simple identifier to easier detect if a user mix up | ||||||
|  |      this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ | ||||||
|  |   long type; | ||||||
|  |  | ||||||
|  |   /* We have a linked list with easy handles */ | ||||||
|  |   struct Curl_one_easy easy;  | ||||||
|  |   /* This is the amount of entries in the linked list above. */ | ||||||
|  |   int num_easy; | ||||||
|  |  | ||||||
|  |   /* this is a linked list of posted messages */ | ||||||
|  |   struct Curl_message *msgs; | ||||||
|  |   /* amount of messages in the queue */ | ||||||
|  |   int num_msgs; | ||||||
|  |   /* Hostname cache */ | ||||||
|  |   curl_hash *hostcache; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CURLM *curl_multi_init(void) | ||||||
|  | { | ||||||
|  |   struct Curl_multi *multi; | ||||||
|  |  | ||||||
|  |   multi = (void *)malloc(sizeof(struct Curl_multi)); | ||||||
|  |  | ||||||
|  |   if(multi) { | ||||||
|  |     memset(multi, 0, sizeof(struct Curl_multi)); | ||||||
|  |     multi->type = CURL_MULTI_HANDLE; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   return (CURLM *) multi; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMcode curl_multi_add_handle(CURLM *multi_handle, | ||||||
|  |                                 CURL *easy_handle) | ||||||
|  | { | ||||||
|  |   struct Curl_multi *multi=(struct Curl_multi *)multi_handle; | ||||||
|  |   struct Curl_one_easy *easy; | ||||||
|  |  | ||||||
|  |   /* First, make some basic checks that the CURLM handle is a good handle */ | ||||||
|  |   if(!GOOD_MULTI_HANDLE(multi)) | ||||||
|  |     return CURLM_BAD_HANDLE; | ||||||
|  |    | ||||||
|  |   /* Verify that we got a somewhat good easy handle too */ | ||||||
|  |   if(!GOOD_EASY_HANDLE(easy_handle)) | ||||||
|  |     return CURLM_BAD_EASY_HANDLE; | ||||||
|  |  | ||||||
|  |   /* Now, time to add an easy handle to the multi stack */ | ||||||
|  |   easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy)); | ||||||
|  |   if(!easy) | ||||||
|  |     return CURLM_OUT_OF_MEMORY; | ||||||
|  |    | ||||||
|  |   /* clean it all first (just to be sure) */ | ||||||
|  |   memset(easy, 0, sizeof(struct Curl_one_easy)); | ||||||
|  |  | ||||||
|  |   /* set the easy handle */ | ||||||
|  |   easy->easy_handle = easy_handle; | ||||||
|  |   easy->state = CURLM_STATE_INIT; | ||||||
|  |    | ||||||
|  |   /* We add this new entry first in the list. We make our 'next' point to the | ||||||
|  |      previous next and our 'prev' point back to the 'first' struct */ | ||||||
|  |   easy->next = multi->easy.next; | ||||||
|  |   easy->prev = &multi->easy;  | ||||||
|  |  | ||||||
|  |   /* make 'easy' the first node in the chain */ | ||||||
|  |   multi->easy.next = easy; | ||||||
|  |  | ||||||
|  |   /* if there was a next node, make sure its 'prev' pointer links back to | ||||||
|  |      the new node */ | ||||||
|  |   if(easy->next) | ||||||
|  |     easy->next->prev = easy; | ||||||
|  |  | ||||||
|  |   /* increase the node-counter */ | ||||||
|  |   multi->num_easy++; | ||||||
|  |  | ||||||
|  |   return CURLM_CALL_MULTI_PERFORM; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMcode curl_multi_remove_handle(CURLM *multi_handle, | ||||||
|  |                                    CURL *curl_handle) | ||||||
|  | { | ||||||
|  |   struct Curl_multi *multi=(struct Curl_multi *)multi_handle; | ||||||
|  |   struct Curl_one_easy *easy; | ||||||
|  |  | ||||||
|  |   /* First, make some basic checks that the CURLM handle is a good handle */ | ||||||
|  |   if(!GOOD_MULTI_HANDLE(multi)) | ||||||
|  |     return CURLM_BAD_HANDLE; | ||||||
|  |    | ||||||
|  |   /* Verify that we got a somewhat good easy handle too */ | ||||||
|  |   if(!GOOD_EASY_HANDLE(curl_handle)) | ||||||
|  |     return CURLM_BAD_EASY_HANDLE; | ||||||
|  |  | ||||||
|  |   /* scan through the list and remove the 'curl_handle' */ | ||||||
|  |   easy = multi->easy.next; | ||||||
|  |   while(easy) { | ||||||
|  |     if(easy->easy_handle == curl_handle) | ||||||
|  |       break; | ||||||
|  |     easy=easy->next; | ||||||
|  |   } | ||||||
|  |   if(easy) { | ||||||
|  |     /* If the 'state' is not INIT or COMPLETED, we might need to do something | ||||||
|  |        nice to put the easy_handle in a good known state when this returns. */ | ||||||
|  |  | ||||||
|  |     /* make the previous node point to our next */ | ||||||
|  |     if(easy->prev) | ||||||
|  |       easy->prev->next = easy->next; | ||||||
|  |     /* make our next point to our previous node */ | ||||||
|  |     if(easy->next) | ||||||
|  |       easy->next->prev = easy->prev; | ||||||
|  |      | ||||||
|  |     /* NOTE NOTE NOTE | ||||||
|  |        We do not touch the easy handle here! */ | ||||||
|  |     free(easy); | ||||||
|  |  | ||||||
|  |     multi->num_easy--; /* one less to care about now */ | ||||||
|  |  | ||||||
|  |     return CURLM_OK; | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     return CURLM_BAD_EASY_HANDLE; /* twasn't found */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMcode curl_multi_fdset(CURLM *multi_handle, | ||||||
|  |                            fd_set *read_fd_set, fd_set *write_fd_set, | ||||||
|  |                            fd_set *exc_fd_set, int *max_fd) | ||||||
|  | { | ||||||
|  |   /* Scan through all the easy handles to get the file descriptors set. | ||||||
|  |      Some easy handles may not have connected to the remote host yet, | ||||||
|  |      and then we must make sure that is done. */ | ||||||
|  |   struct Curl_multi *multi=(struct Curl_multi *)multi_handle; | ||||||
|  |   struct Curl_one_easy *easy; | ||||||
|  |   int this_max_fd=-1; | ||||||
|  |  | ||||||
|  |   if(!GOOD_MULTI_HANDLE(multi)) | ||||||
|  |     return CURLM_BAD_HANDLE; | ||||||
|  |  | ||||||
|  |   *max_fd = -1; /* so far none! */ | ||||||
|  |  | ||||||
|  |   easy=multi->easy.next; | ||||||
|  |   while(easy) { | ||||||
|  |     switch(easy->state) { | ||||||
|  |     default: | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_PERFORM: | ||||||
|  |       /* This should have a set of file descriptors for us to set.  */ | ||||||
|  |       /* after the transfer is done, go DONE */ | ||||||
|  |  | ||||||
|  |       Curl_single_fdset(easy->easy_conn, | ||||||
|  |                         read_fd_set, write_fd_set, | ||||||
|  |                         exc_fd_set, &this_max_fd); | ||||||
|  |  | ||||||
|  |       /* remember the maximum file descriptor */ | ||||||
|  |       if(this_max_fd > *max_fd) | ||||||
|  |         *max_fd = this_max_fd; | ||||||
|  |  | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     easy = easy->next; /* check next handle */ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return CURLM_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) | ||||||
|  | { | ||||||
|  |   struct Curl_multi *multi=(struct Curl_multi *)multi_handle; | ||||||
|  |   struct Curl_one_easy *easy; | ||||||
|  |   bool done; | ||||||
|  |   CURLMcode result=CURLM_OK; | ||||||
|  |  | ||||||
|  |   *running_handles = 0; /* bump this once for every living handle */ | ||||||
|  |  | ||||||
|  |   if(!GOOD_MULTI_HANDLE(multi)) | ||||||
|  |     return CURLM_BAD_HANDLE; | ||||||
|  |  | ||||||
|  |   easy=multi->easy.next; | ||||||
|  |   while(easy) { | ||||||
|  |     switch(easy->state) { | ||||||
|  |     case CURLM_STATE_INIT: | ||||||
|  |       /* init this transfer. */ | ||||||
|  |       easy->result=Curl_pretransfer(easy->easy_handle); | ||||||
|  |       if(CURLE_OK == easy->result) { | ||||||
|  |         /* after init, go CONNECT */ | ||||||
|  |         easy->state = CURLM_STATE_CONNECT; | ||||||
|  |         result = CURLM_CALL_MULTI_PERFORM;  | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_CONNECT: | ||||||
|  |       if (Curl_global_host_cache_use(easy->easy_handle)) { | ||||||
|  |         easy->easy_handle->hostcache = Curl_global_host_cache_get(); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         if (multi->hostcache == NULL) { | ||||||
|  |           multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         easy->easy_handle->hostcache = multi->hostcache; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       /* Connect. We get a connection identifier filled in. */ | ||||||
|  |       easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn); | ||||||
|  |  | ||||||
|  |       /* after connect, go DO */ | ||||||
|  |       if(CURLE_OK == easy->result) { | ||||||
|  |         easy->state = CURLM_STATE_DO; | ||||||
|  |         result = CURLM_CALL_MULTI_PERFORM;  | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_DO: | ||||||
|  |       /* Do the fetch or put request */ | ||||||
|  |       easy->result = Curl_do(&easy->easy_conn); | ||||||
|  |       /* after do, go PERFORM */ | ||||||
|  |       if(CURLE_OK == easy->result) { | ||||||
|  |         if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) { | ||||||
|  |           easy->state = CURLM_STATE_PERFORM; | ||||||
|  |           result = CURLM_CALL_MULTI_PERFORM;  | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_PERFORM: | ||||||
|  |       /* read/write data if it is ready to do so */ | ||||||
|  |       easy->result = Curl_readwrite(easy->easy_conn, &done); | ||||||
|  |       /* hm, when we follow redirects, we may need to go back to the CONNECT | ||||||
|  |          state */ | ||||||
|  |       /* after the transfer is done, go DONE */ | ||||||
|  |       if(TRUE == done) { | ||||||
|  |         /* call this even if the readwrite function returned error */ | ||||||
|  |         easy->result = Curl_posttransfer(easy->easy_handle); | ||||||
|  |         easy->state = CURLM_STATE_DONE; | ||||||
|  |         result = CURLM_CALL_MULTI_PERFORM;  | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_DONE: | ||||||
|  |       /* post-transfer command */ | ||||||
|  |       easy->result = Curl_done(easy->easy_conn); | ||||||
|  |       /* after we have DONE what we're supposed to do, go COMPLETED */ | ||||||
|  |       if(CURLE_OK == easy->result) | ||||||
|  |         easy->state = CURLM_STATE_COMPLETED; | ||||||
|  |       break; | ||||||
|  |     case CURLM_STATE_COMPLETED: | ||||||
|  |       /* 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 | ||||||
|  |          an information message that we are complete. */ | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       return CURLM_INTERNAL_ERROR; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if((CURLM_STATE_COMPLETED != easy->state) && | ||||||
|  |        (CURLE_OK != easy->result)) { | ||||||
|  |       /* | ||||||
|  |        * If an error was returned, and we aren't in completed now, | ||||||
|  |        * then we go to completed and consider this transfer aborted. | ||||||
|  |        */ | ||||||
|  |       easy->state = CURLM_STATE_COMPLETED; | ||||||
|  |     } | ||||||
|  |     else if(CURLM_STATE_COMPLETED != easy->state) | ||||||
|  |       /* this one still lives! */ | ||||||
|  |       (*running_handles)++; | ||||||
|  |  | ||||||
|  |     easy = easy->next; /* operate on next handle */ | ||||||
|  |   } | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMcode curl_multi_cleanup(CURLM *multi_handle) | ||||||
|  | { | ||||||
|  |   struct Curl_multi *multi=(struct Curl_multi *)multi_handle; | ||||||
|  |   if(GOOD_MULTI_HANDLE(multi)) { | ||||||
|  |     multi->type = 0; /* not good anymore */ | ||||||
|  |     curl_hash_destroy(multi->hostcache); | ||||||
|  |     /* remove all easy handles */ | ||||||
|  |  | ||||||
|  |     free(multi); | ||||||
|  |  | ||||||
|  |     return CURLM_OK; | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |     return CURLM_BAD_HANDLE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * local variables: | ||||||
|  |  * eval: (load-file "../curl-mode.el") | ||||||
|  |  * end: | ||||||
|  |  * vim600: fdm=marker | ||||||
|  |  * vim: et sw=2 ts=2 sts=2 tw=78 | ||||||
|  |  */ | ||||||
							
								
								
									
										189
									
								
								lib/multi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								lib/multi.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | |||||||
|  | #ifndef __CURL_MULTI_H | ||||||
|  | #define __CURL_MULTI_H | ||||||
|  | /***************************************************************************** | ||||||
|  |  *                                  _   _ ____  _      | ||||||
|  |  *  Project                     ___| | | |  _ \| |     | ||||||
|  |  *                             / __| | | | |_) | |     | ||||||
|  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  |  *                             \___|\___/|_| \_\_____| | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  |  * | ||||||
|  |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
|  |  * | ||||||
|  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | ||||||
|  |  * copies of the Software, and permit persons to whom the Software is | ||||||
|  |  * furnished to do so, under the terms of the MPL or the MIT/X-derivate | ||||||
|  |  * licenses. You may pick one of these licenses. | ||||||
|  |  * | ||||||
|  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||||||
|  |  * KIND, either express or implied. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  *****************************************************************************/ | ||||||
|  | /* | ||||||
|  |   This is meant to be the "external" header file. Don't give away any | ||||||
|  |   internals here! | ||||||
|  |  | ||||||
|  |   This document presents a mixture of ideas from at least: | ||||||
|  |   - Daniel Stenberg | ||||||
|  |   - Steve Dekorte | ||||||
|  |   - Sterling Hughes | ||||||
|  |   - Ben Greear | ||||||
|  |  | ||||||
|  |   ------------------------------------------- | ||||||
|  |   GOALS | ||||||
|  |  | ||||||
|  |   o Enable a "pull" interface. The application that uses libcurl decides where | ||||||
|  |     and when to ask libcurl to get/send data. | ||||||
|  |  | ||||||
|  |   o Enable multiple simultaneous transfers in the same thread without making it | ||||||
|  |     complicated for the application. | ||||||
|  |  | ||||||
|  |   o Enable the application to select() on its own file descriptors and curl's | ||||||
|  |     file descriptors simultaneous easily. | ||||||
|  |    | ||||||
|  |   Example sources using this interface is here: ../multi/ | ||||||
|  |  | ||||||
|  | */ | ||||||
|  | #ifdef HAVE_SYS_SOCKET_H | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #endif | ||||||
|  | #ifdef HAVE_WINSOCK_H | ||||||
|  | #include <winsock.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | typedef void CURLM; | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |   CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */ | ||||||
|  |   CURLM_OK, | ||||||
|  |   CURLM_BAD_HANDLE,      /* the passed-in handle is not a valid CURLM handle */ | ||||||
|  |   CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ | ||||||
|  |   CURLM_OUT_OF_MEMORY,   /* if you ever get this, you're in deep sh*t */ | ||||||
|  |   CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */ | ||||||
|  |   CURLM_LAST | ||||||
|  | } CURLMcode; | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |   CURLMSG_NONE, /* first, not used */ | ||||||
|  |   CURLMSG_DONE, /* This easy handle has completed. 'whatever' points to | ||||||
|  |                    the CURLcode of the transfer */ | ||||||
|  |   CURLMSG_LAST /* last, not used */ | ||||||
|  | } CURLMSG; | ||||||
|  |  | ||||||
|  | struct CURLMsg { | ||||||
|  |   CURLMSG msg;       /* what this message means */ | ||||||
|  |   CURL *easy_handle; /* the handle it concerns */ | ||||||
|  |   union { | ||||||
|  |     void *whatever;    /* message-specific data */ | ||||||
|  |     CURLcode result;   /* return code for transfer */ | ||||||
|  |   } data; | ||||||
|  | }; | ||||||
|  | typedef struct CURLMsg CURLMsg; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Name:    curl_multi_init() | ||||||
|  |  * | ||||||
|  |  * Desc:    inititalize multi-style curl usage | ||||||
|  |  * Returns: a new CURLM handle to use in all 'curl_multi' functions. | ||||||
|  |  */ | ||||||
|  | CURLM *curl_multi_init(void); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Name:    curl_multi_add_handle() | ||||||
|  |  * | ||||||
|  |  * Desc:    add a standard curl handle to the multi stack | ||||||
|  |  * Returns: CURLMcode type, general multi error code. | ||||||
|  |  */ | ||||||
|  | CURLMcode curl_multi_add_handle(CURLM *multi_handle, | ||||||
|  |                                 CURL *curl_handle); | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  |   * Name:    curl_multi_remove_handle() | ||||||
|  |   * | ||||||
|  |   * Desc:    removes a curl handle from the multi stack again | ||||||
|  |   * Returns: CURLMcode type, general multi error code. | ||||||
|  |   */ | ||||||
|  | CURLMcode curl_multi_remove_handle(CURLM *multi_handle, | ||||||
|  |                                    CURL *curl_handle); | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  |   * Name:    curl_multi_fdset() | ||||||
|  |   * | ||||||
|  |   * Desc:    Ask curl for its fd_set sets. The app can use these to select() or | ||||||
|  |   *          poll() on. We want curl_multi_perform() called as soon as one of | ||||||
|  |   *          them are ready. | ||||||
|  |   * Returns: CURLMcode type, general multi error code. | ||||||
|  |   */ | ||||||
|  | CURLMcode curl_multi_fdset(CURLM *multi_handle, | ||||||
|  |                            fd_set *read_fd_set, | ||||||
|  |                            fd_set *write_fd_set, | ||||||
|  |                            fd_set *exc_fd_set, | ||||||
|  |                            int *max_fd); | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  |   * Name:    curl_multi_perform() | ||||||
|  |   * | ||||||
|  |   * Desc:    When the app thinks there's data available for curl it calls this | ||||||
|  |   *          function to read/write whatever there is right now. This returns | ||||||
|  |   *          as soon as the reads and writes are done. This function does not | ||||||
|  |   *          require that there actually is data available for reading or that | ||||||
|  |   *          data can be written, it can be called just in case. It returns | ||||||
|  |   *          the number of handles that still transfer data in the second | ||||||
|  |   *          argument's integer-pointer. | ||||||
|  |   * | ||||||
|  |   * Returns: CURLMcode type, general multi error code. *NOTE* that this only | ||||||
|  |   *          returns errors etc regarding the whole multi stack. There might | ||||||
|  |   *          still have occurred problems on invidual transfers even when this | ||||||
|  |   *          returns OK. | ||||||
|  |   */ | ||||||
|  | CURLMcode curl_multi_perform(CURLM *multi_handle, | ||||||
|  |                              int *running_handles); | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  |   * Name:    curl_multi_cleanup() | ||||||
|  |   * | ||||||
|  |   * Desc:    Cleans up and removes a whole multi stack. It does not free or | ||||||
|  |   *          touch any individual easy handles in any way. We need to define | ||||||
|  |   *          in what state those handles will be if this function is called | ||||||
|  |   *          in the middle of a transfer. | ||||||
|  |   * Returns: CURLMcode type, general multi error code. | ||||||
|  |   */ | ||||||
|  | CURLMcode curl_multi_cleanup(CURLM *multi_handle); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Name:    curl_multi_info_read() | ||||||
|  |  * | ||||||
|  |  * Desc:    Ask the multi handle if there's any messages/informationals from | ||||||
|  |  *          the individual transfers. Messages include informationals such as | ||||||
|  |  *          error code from the transfer or just the fact that a transfer is | ||||||
|  |  *          completed. More details on these should be written down as well. | ||||||
|  |  * | ||||||
|  |  *          Repeated calls to this function will return a new struct each | ||||||
|  |  *          time, until a special "end of msgs" struct is returned as a signal | ||||||
|  |  *          that there is no more to get at this point. | ||||||
|  |  * | ||||||
|  |  *          The data the returned pointer points to will not survive calling | ||||||
|  |  *          curl_multi_cleanup(). | ||||||
|  |  * | ||||||
|  |  *          The 'CURLMsg' struct is meant to be very simple and only contain | ||||||
|  |  *          very basic informations. If more involved information is wanted, | ||||||
|  |  *          we will provide the particular "transfer handle" in that struct | ||||||
|  |  *          and that should/could/would be used in subsequent | ||||||
|  |  *          curl_easy_getinfo() calls (or similar). The point being that we | ||||||
|  |  *          must never expose complex structs to applications, as then we'll | ||||||
|  |  *          undoubtably get backwards compatibility problems in the future. | ||||||
|  |  * | ||||||
|  |  * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out | ||||||
|  |  *          of structs. It also writes the number of messages left in the | ||||||
|  |  *          queue (after this read) in the integer the second argument points | ||||||
|  |  *          to. | ||||||
|  |  */ | ||||||
|  | CURLMsg *curl_multi_info_read(CURLM *multi_handle, | ||||||
|  |                               int *msgs_in_queue); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -157,7 +157,7 @@ int Curl_parsenetrc(char *host, | |||||||
| 	  } | 	  } | ||||||
| 	  else if(state_password) { | 	  else if(state_password) { | ||||||
| 	    strncpy(password, tok, PASSWORDSIZE-1); | 	    strncpy(password, tok, PASSWORDSIZE-1); | ||||||
| #if _NETRC_DEBUG | #ifdef _NETRC_DEBUG | ||||||
| 	    printf("PASSWORD: %s\n", password); | 	    printf("PASSWORD: %s\n", password); | ||||||
| #endif | #endif | ||||||
| 	    state_password=0; | 	    state_password=0; | ||||||
|   | |||||||
| @@ -111,23 +111,25 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer) | |||||||
|     /* mistake filter */ |     /* mistake filter */ | ||||||
|     break; |     break; | ||||||
|   case TIMER_STARTSINGLE: |   case TIMER_STARTSINGLE: | ||||||
|     /* This is set at the start of a single fetch, there may be several |     /* This is set at the start of a single fetch */ | ||||||
|        fetches within an operation, why we add all other times relative |  | ||||||
|        to this one */ |  | ||||||
|     data->progress.t_startsingle = Curl_tvnow(); |     data->progress.t_startsingle = Curl_tvnow(); | ||||||
|     break; |     break; | ||||||
|  |  | ||||||
|   case TIMER_NAMELOOKUP: |   case TIMER_NAMELOOKUP: | ||||||
|     data->progress.t_nslookup += |     data->progress.t_nslookup = | ||||||
|       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000; |       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; | ||||||
|     break; |     break; | ||||||
|   case TIMER_CONNECT: |   case TIMER_CONNECT: | ||||||
|     data->progress.t_connect += |     data->progress.t_connect = | ||||||
|       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000; |       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; | ||||||
|     break; |     break; | ||||||
|   case TIMER_PRETRANSFER: |   case TIMER_PRETRANSFER: | ||||||
|     data->progress.t_pretransfer += |     data->progress.t_pretransfer = | ||||||
|       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000; |       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; | ||||||
|  |     break; | ||||||
|  |   case TIMER_STARTTRANSFER: | ||||||
|  |     data->progress.t_starttransfer = | ||||||
|  |       (double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0; | ||||||
|     break; |     break; | ||||||
|   case TIMER_POSTRANSFER: |   case TIMER_POSTRANSFER: | ||||||
|     /* this is the normal end-of-transfer thing */ |     /* this is the normal end-of-transfer thing */ | ||||||
| @@ -227,7 +229,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) | |||||||
|   /* The exact time spent so far (from the start) */ |   /* The exact time spent so far (from the start) */ | ||||||
|   timespent = (double)Curl_tvdiff (now, data->progress.start)/1000; |   timespent = (double)Curl_tvdiff (now, data->progress.start)/1000; | ||||||
|  |  | ||||||
|   data->progress.timespent = (long)timespent; |   data->progress.timespent = timespent; | ||||||
|  |  | ||||||
|   /* The average download speed this far */ |   /* The average download speed this far */ | ||||||
|   data->progress.dlspeed = |   data->progress.dlspeed = | ||||||
| @@ -275,6 +277,8 @@ int Curl_pgrsUpdate(struct connectdata *conn) | |||||||
|     /* Figure out the exact time for the time span */ |     /* Figure out the exact time for the time span */ | ||||||
|     span_ms = Curl_tvdiff(now, |     span_ms = Curl_tvdiff(now, | ||||||
|                           data->progress.speeder_time[checkindex]); |                           data->progress.speeder_time[checkindex]); | ||||||
|  |     if(0 == span_ms) | ||||||
|  |       span_ms=1; /* at least one millisecond MUST have passed */ | ||||||
|  |  | ||||||
|     /* Calculate the average speed the last 'countindex' seconds */ |     /* Calculate the average speed the last 'countindex' seconds */ | ||||||
|     data->progress.current_speed = |     data->progress.current_speed = | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ typedef enum { | |||||||
|   TIMER_NAMELOOKUP, |   TIMER_NAMELOOKUP, | ||||||
|   TIMER_CONNECT, |   TIMER_CONNECT, | ||||||
|   TIMER_PRETRANSFER, |   TIMER_PRETRANSFER, | ||||||
|  |   TIMER_STARTTRANSFER, | ||||||
|   TIMER_POSTRANSFER, |   TIMER_POSTRANSFER, | ||||||
|   TIMER_STARTSINGLE, |   TIMER_STARTSINGLE, | ||||||
|   TIMER_LAST /* must be last */ |   TIMER_LAST /* must be last */ | ||||||
|   | |||||||
| @@ -362,11 +362,11 @@ Curl_sec_vfprintf(struct connectdata *conn, FILE *f, const char *fmt, va_list ap | |||||||
|                                conn); |                                conn); | ||||||
|     free(buf); |     free(buf); | ||||||
|     if(len < 0) { |     if(len < 0) { | ||||||
| 	failf(conn->data, "Failed to encode command.\n"); | 	failf(conn->data, "Failed to encode command."); | ||||||
| 	return -1; | 	return -1; | ||||||
|     } |     } | ||||||
|     if(Curl_base64_encode(enc, len, &buf) < 0){ |     if(Curl_base64_encode(enc, len, &buf) < 0){ | ||||||
|       failf(conn->data, "Out of memory base64-encoding.\n"); |       failf(conn->data, "Out of memory base64-encoding."); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     if(conn->command_prot == prot_safe) |     if(conn->command_prot == prot_safe) | ||||||
| @@ -421,7 +421,7 @@ sec_prot_internal(struct connectdata *conn, int level) | |||||||
|       return -1; |       return -1; | ||||||
|  |  | ||||||
|     if(conn->data->state.buffer[0] != '2'){ |     if(conn->data->state.buffer[0] != '2'){ | ||||||
|       failf(conn->data, "Failed to set protection buffer size.\n"); |       failf(conn->data, "Failed to set protection buffer size."); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     conn->buffer_size = s; |     conn->buffer_size = s; | ||||||
| @@ -441,7 +441,7 @@ sec_prot_internal(struct connectdata *conn, int level) | |||||||
|     return -1; |     return -1; | ||||||
|  |  | ||||||
|   if(conn->data->state.buffer[0] != '2'){ |   if(conn->data->state.buffer[0] != '2'){ | ||||||
|     failf(conn->data, "Failed to set protection level.\n"); |     failf(conn->data, "Failed to set protection level."); | ||||||
|     return -1; |     return -1; | ||||||
|   } |   } | ||||||
|      |      | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								lib/sendf.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								lib/sendf.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * In order to be useful for every potential user, curl and libcurl are |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  * dual-licensed under the MPL and the MIT/X-derivate licenses. |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
| @@ -26,6 +26,15 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  | #include <errno.h> | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SYS_TYPES_H | ||||||
|  | #include <sys/types.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SYS_SOCKET_H | ||||||
|  | #include <sys/socket.h>	/* required for send() & recv() prototypes */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef HAVE_UNISTD_H | #ifdef HAVE_UNISTD_H | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| @@ -133,8 +142,9 @@ void Curl_infof(struct SessionHandle *data, const char *fmt, ...) | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Curl_failf() is for messages stating why we failed, the LAST one will be | /* Curl_failf() is for messages stating why we failed. | ||||||
|    returned for the user (if requested) */ |  * The message SHALL NOT include any LF or CR. | ||||||
|  |  */ | ||||||
|  |  | ||||||
| void Curl_failf(struct SessionHandle *data, const char *fmt, ...) | void Curl_failf(struct SessionHandle *data, const char *fmt, ...) | ||||||
| { | { | ||||||
| @@ -152,7 +162,7 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn, | |||||||
|                     const char *fmt, ...) |                     const char *fmt, ...) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|   size_t bytes_written; |   ssize_t bytes_written; | ||||||
|   CURLcode result; |   CURLcode result; | ||||||
|   char *s; |   char *s; | ||||||
|   va_list ap; |   va_list ap; | ||||||
| @@ -179,26 +189,32 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn, | |||||||
|  */ |  */ | ||||||
| CURLcode Curl_write(struct connectdata *conn, int sockfd, | CURLcode Curl_write(struct connectdata *conn, int sockfd, | ||||||
|                     void *mem, size_t len, |                     void *mem, size_t len, | ||||||
|                     size_t *written) |                     ssize_t *written) | ||||||
| { | { | ||||||
|   size_t bytes_written; |   ssize_t bytes_written; | ||||||
|  |  | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|   /* SSL_write() is said to return 'int' while write() and send() returns |   /* SSL_write() is said to return 'int' while write() and send() returns | ||||||
|      'size_t' */ |      'size_t' */ | ||||||
|   int ssl_bytes; |  | ||||||
|   if (conn->ssl.use) { |   if (conn->ssl.use) { | ||||||
|     int loop=100; /* just a precaution to never loop endlessly */ |     int err; | ||||||
|     while(loop--) { |     int rc = SSL_write(conn->ssl.handle, mem, len); | ||||||
|       ssl_bytes = SSL_write(conn->ssl.handle, mem, len); |  | ||||||
|       if((0 >= ssl_bytes) || |     if(rc < 0) { | ||||||
|          (SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle, |       err = SSL_get_error(conn->ssl.handle, rc); | ||||||
|                                                 ssl_bytes) )) { |      | ||||||
|         /* this converts from signed to unsigned... */ |       switch(err) { | ||||||
|         bytes_written = ssl_bytes; |       case SSL_ERROR_WANT_READ: | ||||||
|         break; |       case SSL_ERROR_WANT_WRITE: | ||||||
|  |         /* this is basicly the EWOULDBLOCK equivalent */ | ||||||
|  |         *written = 0; | ||||||
|  |         return CURLE_OK; | ||||||
|       } |       } | ||||||
|  |       /* a true error */ | ||||||
|  |       failf(conn->data, "SSL_write() return error %d\n", err); | ||||||
|  |       return CURLE_WRITE_ERROR; | ||||||
|     } |     } | ||||||
|  |     bytes_written = rc; | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| #endif | #endif | ||||||
| @@ -208,13 +224,27 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd, | |||||||
|     } |     } | ||||||
|     else |     else | ||||||
| #endif /* KRB4 */ | #endif /* KRB4 */ | ||||||
|  |     { | ||||||
|       bytes_written = swrite(sockfd, mem, len); |       bytes_written = swrite(sockfd, mem, len); | ||||||
|  |     } | ||||||
|  |     if(-1 == bytes_written) { | ||||||
|  | #ifdef WIN32 | ||||||
|  |       if(WSAEWOULDBLOCK == GetLastError()) | ||||||
|  | #else | ||||||
|  |       if(EWOULDBLOCK == errno) | ||||||
|  | #endif | ||||||
|  |       { | ||||||
|  |         /* this is just a case of EWOULDBLOCK */ | ||||||
|  |         *written=0; | ||||||
|  |         return CURLE_OK; | ||||||
|  |       } | ||||||
|  |     } | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   *written = bytes_written; |   *written = bytes_written; | ||||||
|   return (bytes_written==len)?CURLE_OK:CURLE_WRITE_ERROR; |   return (-1 != bytes_written)?CURLE_OK:CURLE_WRITE_ERROR; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* client_write() sends data to the write callback(s) | /* client_write() sends data to the write callback(s) | ||||||
| @@ -258,26 +288,47 @@ CURLcode Curl_client_write(struct SessionHandle *data, | |||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Internal read-from-socket function. This is meant to deal with plain |  * Internal read-from-socket function. This is meant to deal with plain | ||||||
|  * sockets, SSL sockets and kerberos sockets. |  * sockets, SSL sockets and kerberos sockets. | ||||||
|  |  * | ||||||
|  |  * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return | ||||||
|  |  * a regular CURLcode value. | ||||||
|  */ |  */ | ||||||
| CURLcode Curl_read(struct connectdata *conn, int sockfd, | int Curl_read(struct connectdata *conn, | ||||||
|                    char *buf, size_t buffersize, |               int sockfd, | ||||||
|  |               char *buf, | ||||||
|  |               size_t buffersize, | ||||||
|               ssize_t *n) |               ssize_t *n) | ||||||
| { | { | ||||||
|   ssize_t nread; |   ssize_t nread; | ||||||
|  |  | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|   if (conn->ssl.use) { |   if (conn->ssl.use) { | ||||||
|     int loop=100; /* just a precaution to never loop endlessly */ |     bool loop=TRUE; | ||||||
|     while(loop--) { |     int err; | ||||||
|  |     do { | ||||||
|       nread = SSL_read(conn->ssl.handle, buf, buffersize); |       nread = SSL_read(conn->ssl.handle, buf, buffersize); | ||||||
|       if((-1 != nread) || |  | ||||||
|          (SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) )) |       if(nread >= 0) | ||||||
|  |         /* successful read */ | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       err = SSL_get_error(conn->ssl.handle, nread); | ||||||
|  |  | ||||||
|  |       switch(err) { | ||||||
|  |       case SSL_ERROR_NONE: /* this is not an error */ | ||||||
|  |       case SSL_ERROR_ZERO_RETURN: /* no more data */ | ||||||
|  |         loop=0; /* get out of loop */ | ||||||
|  |         break; | ||||||
|  |       case SSL_ERROR_WANT_READ: | ||||||
|  |       case SSL_ERROR_WANT_WRITE: | ||||||
|  |         /* if there's data pending, then we re-invoke SSL_read() */ | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|  |     } while(loop); | ||||||
|  |     if(loop && SSL_pending(conn->ssl.handle)) | ||||||
|  |       return -1; /* basicly EWOULDBLOCK */ | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
| #endif | #endif | ||||||
| @@ -287,6 +338,16 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd, | |||||||
|     else |     else | ||||||
| #endif | #endif | ||||||
|       nread = sread (sockfd, buf, buffersize); |       nread = sread (sockfd, buf, buffersize); | ||||||
|  |  | ||||||
|  |     if(-1 == nread) { | ||||||
|  | #ifdef WIN32 | ||||||
|  |       if(WSAEWOULDBLOCK == GetLastError()) | ||||||
|  | #else | ||||||
|  |       if(EWOULDBLOCK == errno) | ||||||
|  | #endif | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|   } |   } | ||||||
| #endif /* USE_SSLEAY */ | #endif /* USE_SSLEAY */ | ||||||
|   | |||||||
| @@ -45,12 +45,12 @@ CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr, | |||||||
|                            size_t len); |                            size_t len); | ||||||
|  |  | ||||||
| /* internal read-function, does plain socket, SSL and krb4 */ | /* internal read-function, does plain socket, SSL and krb4 */ | ||||||
| CURLcode Curl_read(struct connectdata *conn, int sockfd, | int Curl_read(struct connectdata *conn, int sockfd, | ||||||
|               char *buf, size_t buffersize, |               char *buf, size_t buffersize, | ||||||
|               ssize_t *n); |               ssize_t *n); | ||||||
| /* internal write-function, does plain socket, SSL and krb4 */ | /* internal write-function, does plain socket, SSL and krb4 */ | ||||||
| CURLcode Curl_write(struct connectdata *conn, int sockfd, | CURLcode Curl_write(struct connectdata *conn, int sockfd, | ||||||
|                     void *mem, size_t len, |                     void *mem, size_t len, | ||||||
|                     size_t *written); |                     ssize_t *written); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								lib/setup.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								lib/setup.h
									
									
									
									
									
								
							| @@ -41,13 +41,19 @@ | |||||||
|  |  | ||||||
| #else | #else | ||||||
| #ifdef WIN32 | #ifdef WIN32 | ||||||
| /* include the hand-modified win32 adjusted config.h! */ | /* hand-modified win32 config.h! */ | ||||||
| #include "../config-win32.h" | #include "config-win32.h" | ||||||
| #endif | #endif | ||||||
|  | #ifdef macintosh | ||||||
|  | /* hand-modified MacOS config.h! */ | ||||||
|  | #include "config-mac.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef __cplusplus        /* (rabe) */ | #ifndef __cplusplus        /* (rabe) */ | ||||||
| typedef char bool; | typedef unsigned char bool; | ||||||
|  | #define typedef_bool | ||||||
| #endif                     /* (rabe) */ | #endif                     /* (rabe) */ | ||||||
|  |  | ||||||
| #ifdef NEED_REENTRANT | #ifdef NEED_REENTRANT | ||||||
| @@ -88,11 +94,12 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO) | |||||||
| #ifdef	VMS | #ifdef	VMS | ||||||
| #include "../include/curl/stdcheaders.h" | #include "../include/curl/stdcheaders.h" | ||||||
| #else | #else | ||||||
| #include "curl/stdcheaders.h" | #include <curl/stdcheaders.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #else | #else | ||||||
| #ifdef _AIX | #ifdef _AIX | ||||||
| #include "curl/stdcheaders.h" | #include <curl/stdcheaders.h> | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -110,13 +117,13 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO) | |||||||
| #define sclose(x) closesocket(x) | #define sclose(x) closesocket(x) | ||||||
| #define sread(x,y,z) recv(x,y,z,0) | #define sread(x,y,z) recv(x,y,z,0) | ||||||
| #define swrite(x,y,z) (size_t)send(x,y,z,0) | #define swrite(x,y,z) (size_t)send(x,y,z,0) | ||||||
| #define myalarm(x) /* win32 is a silly system */ | #undef HAVE_ALARM | ||||||
| #else | #else | ||||||
|      /* gcc-for-win is still good :) */ |      /* gcc-for-win is still good :) */ | ||||||
| #define sclose(x) close(x) | #define sclose(x) close(x) | ||||||
| #define sread(x,y,z) recv(x,y,z,0) | #define sread(x,y,z) recv(x,y,z,0) | ||||||
| #define swrite(x,y,z) send(x,y,z,0) | #define swrite(x,y,z) send(x,y,z,0) | ||||||
| #define myalarm(x) alarm(x) | #define HAVE_ALARM | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define PATH_CHAR     ";" | #define PATH_CHAR     ";" | ||||||
| @@ -127,7 +134,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO) | |||||||
| #define sclose(x) close(x) | #define sclose(x) close(x) | ||||||
| #define sread(x,y,z) recv(x,y,z,0) | #define sread(x,y,z) recv(x,y,z,0) | ||||||
| #define swrite(x,y,z) send(x,y,z,0) | #define swrite(x,y,z) send(x,y,z,0) | ||||||
| #define myalarm(x) alarm(x) | #define HAVE_ALARM | ||||||
|  |  | ||||||
| #define PATH_CHAR     ":" | #define PATH_CHAR     ":" | ||||||
| #define DIR_CHAR      "/" | #define DIR_CHAR      "/" | ||||||
|   | |||||||
							
								
								
									
										284
									
								
								lib/ssluse.c
									
									
									
									
									
								
							
							
						
						
									
										284
									
								
								lib/ssluse.c
									
									
									
									
									
								
							| @@ -5,7 +5,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * In order to be useful for every potential user, curl and libcurl are |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  * dual-licensed under the MPL and the MIT/X-derivate licenses. |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
| @@ -22,11 +22,12 @@ | |||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * The original SSL code was written by |  * The original SSL code for curl was written by | ||||||
|  * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi> |  * Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi> | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "setup.h" | #include "setup.h" | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  |  | ||||||
| @@ -42,6 +43,12 @@ | |||||||
| #include "memdebug.h" | #include "memdebug.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if OPENSSL_VERSION_NUMBER >= 0x0090581fL | ||||||
|  | #define HAVE_SSL_GET1_SESSION 1 | ||||||
|  | #else | ||||||
|  | #undef HAVE_SSL_GET1_SESSION | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if OPENSSL_VERSION_NUMBER >= 0x00904100L | #if OPENSSL_VERSION_NUMBER >= 0x00904100L | ||||||
| #define HAVE_USERDATA_IN_PWD_CALLBACK 1 | #define HAVE_USERDATA_IN_PWD_CALLBACK 1 | ||||||
| #else | #else | ||||||
| @@ -73,10 +80,8 @@ static int passwd_callback(char *buf, int num, int verify | |||||||
| } | } | ||||||
|  |  | ||||||
| static | static | ||||||
| bool seed_enough(struct connectdata *conn, /* unused for now */ | bool seed_enough(int nread) | ||||||
|                  int nread) |  | ||||||
| { | { | ||||||
|   conn = NULL; /* to prevent compiler warnings */ |  | ||||||
| #ifdef HAVE_RAND_STATUS | #ifdef HAVE_RAND_STATUS | ||||||
|   nread = 0; /* to prevent compiler warnings */ |   nread = 0; /* to prevent compiler warnings */ | ||||||
|  |  | ||||||
| @@ -92,11 +97,10 @@ bool seed_enough(struct connectdata *conn, /* unused for now */ | |||||||
| } | } | ||||||
|  |  | ||||||
| static | static | ||||||
| int random_the_seed(struct connectdata *conn) | int random_the_seed(struct SessionHandle *data) | ||||||
| { | { | ||||||
|   char *buf = conn->data->state.buffer; /* point to the big buffer */ |   char *buf = data->state.buffer; /* point to the big buffer */ | ||||||
|   int nread=0; |   int nread=0; | ||||||
|   struct SessionHandle *data=conn->data; |  | ||||||
|  |  | ||||||
|   /* Q: should we add support for a random file name as a libcurl option? |   /* Q: should we add support for a random file name as a libcurl option? | ||||||
|      A: Yes, it is here */ |      A: Yes, it is here */ | ||||||
| @@ -112,7 +116,7 @@ int random_the_seed(struct connectdata *conn) | |||||||
|     nread += RAND_load_file((data->set.ssl.random_file? |     nread += RAND_load_file((data->set.ssl.random_file? | ||||||
|                              data->set.ssl.random_file:RANDOM_FILE), |                              data->set.ssl.random_file:RANDOM_FILE), | ||||||
|                             16384); |                             16384); | ||||||
|     if(seed_enough(conn, nread)) |     if(seed_enough(nread)) | ||||||
|       return nread; |       return nread; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -131,7 +135,7 @@ int random_the_seed(struct connectdata *conn) | |||||||
|     int ret = RAND_egd(data->set.ssl.egdsocket?data->set.ssl.egdsocket:EGD_SOCKET); |     int ret = RAND_egd(data->set.ssl.egdsocket?data->set.ssl.egdsocket:EGD_SOCKET); | ||||||
|     if(-1 != ret) { |     if(-1 != ret) { | ||||||
|       nread += ret; |       nread += ret; | ||||||
|       if(seed_enough(conn, nread)) |       if(seed_enough(nread)) | ||||||
|         return nread; |         return nread; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -163,45 +167,67 @@ int random_the_seed(struct connectdata *conn) | |||||||
|   if ( buf[0] ) { |   if ( buf[0] ) { | ||||||
|     /* we got a file name to try */ |     /* we got a file name to try */ | ||||||
|     nread += RAND_load_file(buf, 16384); |     nread += RAND_load_file(buf, 16384); | ||||||
|     if(seed_enough(conn, nread)) |     if(seed_enough(nread)) | ||||||
|       return nread; |       return nread; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   infof(conn->data, "Your connection is using a weak random seed!\n"); |   infof(data, "libcurl is now using a weak random seed!\n"); | ||||||
|   return nread; |   return nread; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef SSL_FILETYPE_ENGINE | ||||||
|  | #define SSL_FILETYPE_ENGINE 42 | ||||||
|  | #endif | ||||||
|  | static int do_file_type(const char *type) | ||||||
|  | { | ||||||
|  |   if (!type || !type[0]) | ||||||
|  |     return SSL_FILETYPE_PEM; | ||||||
|  |   if (curl_strequal(type, "PEM")) | ||||||
|  |     return SSL_FILETYPE_PEM; | ||||||
|  |   if (curl_strequal(type, "DER")) | ||||||
|  |     return SSL_FILETYPE_ASN1; | ||||||
|  |   if (curl_strequal(type, "ENG")) | ||||||
|  |     return SSL_FILETYPE_ENGINE; | ||||||
|  |   return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
| static | static | ||||||
| int cert_stuff(struct connectdata *conn, | int cert_stuff(struct connectdata *conn, | ||||||
|                char *cert_file, |                char *cert_file, | ||||||
|                char *key_file) |                const char *cert_type, | ||||||
|  |                char *key_file, | ||||||
|  |                const char *key_type) | ||||||
| { | { | ||||||
|   struct SessionHandle *data = conn->data; |   struct SessionHandle *data = conn->data; | ||||||
|  |   int file_type; | ||||||
|  |  | ||||||
|   if (cert_file != NULL) { |   if (cert_file != NULL) { | ||||||
|     SSL *ssl; |     SSL *ssl; | ||||||
|     X509 *x509; |     X509 *x509; | ||||||
|  |  | ||||||
|     if(data->set.cert_passwd) { |     if(data->set.key_passwd) { | ||||||
| #ifndef HAVE_USERDATA_IN_PWD_CALLBACK | #ifndef HAVE_USERDATA_IN_PWD_CALLBACK | ||||||
|       /* |       /* | ||||||
|        * If password has been given, we store that in the global |        * If password has been given, we store that in the global | ||||||
|        * area (*shudder*) for a while: |        * area (*shudder*) for a while: | ||||||
|        */ |        */ | ||||||
|       strcpy(global_passwd, data->set.cert_passwd); |       strcpy(global_passwd, data->set.key_passwd); | ||||||
| #else | #else | ||||||
|       /* |       /* | ||||||
|        * We set the password in the callback userdata |        * We set the password in the callback userdata | ||||||
|        */ |        */ | ||||||
|       SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.cert_passwd); |       SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, | ||||||
|  |                                              data->set.key_passwd); | ||||||
| #endif | #endif | ||||||
|       /* Set passwd callback: */ |       /* Set passwd callback: */ | ||||||
|       SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); |       SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|     if (SSL_CTX_use_certificate_file(conn->ssl.ctx, |     if (SSL_CTX_use_certificate_file(conn->ssl.ctx, | ||||||
| 				     cert_file, | 				     cert_file, | ||||||
| 				     SSL_FILETYPE_PEM) != 1) { | 				     SSL_FILETYPE_PEM) != 1) { | ||||||
|       failf(data, "unable to set certificate file (wrong password?)\n"); |       failf(data, "unable to set certificate file (wrong password?)"); | ||||||
|       return(0); |       return(0); | ||||||
|     } |     } | ||||||
|     if (key_file == NULL) |     if (key_file == NULL) | ||||||
| @@ -210,9 +236,86 @@ int cert_stuff(struct connectdata *conn, | |||||||
|     if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, |     if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, | ||||||
| 				    key_file, | 				    key_file, | ||||||
| 				    SSL_FILETYPE_PEM) != 1) { | 				    SSL_FILETYPE_PEM) != 1) { | ||||||
|       failf(data, "unable to set public key file\n"); |       failf(data, "unable to set public key file"); | ||||||
|       return(0); |       return(0); | ||||||
|     } |     } | ||||||
|  | #else | ||||||
|  |     /* The '#ifdef 0' section above was removed on 17-dec-2001 */ | ||||||
|  |  | ||||||
|  |     file_type = do_file_type(cert_type); | ||||||
|  |  | ||||||
|  |     switch(file_type) { | ||||||
|  |     case SSL_FILETYPE_PEM: | ||||||
|  |     case SSL_FILETYPE_ASN1: | ||||||
|  |       if (SSL_CTX_use_certificate_file(conn->ssl.ctx, | ||||||
|  |                                        cert_file, | ||||||
|  |                                        file_type) != 1) { | ||||||
|  |         failf(data, "unable to set certificate file (wrong password?)"); | ||||||
|  |         return 0; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case SSL_FILETYPE_ENGINE: | ||||||
|  |       failf(data, "file type ENG for certificate not implemented"); | ||||||
|  |       return 0; | ||||||
|  |  | ||||||
|  |     default: | ||||||
|  |       failf(data, "not supported file type '%s' for certificate", cert_type); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     file_type = do_file_type(key_type); | ||||||
|  |  | ||||||
|  |     switch(file_type) { | ||||||
|  |     case SSL_FILETYPE_PEM: | ||||||
|  |       if (key_file == NULL) | ||||||
|  |         /* cert & key can only be in PEM case in the same file */ | ||||||
|  |         key_file=cert_file; | ||||||
|  |     case SSL_FILETYPE_ASN1: | ||||||
|  |       if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, | ||||||
|  |                                       key_file, | ||||||
|  |                                       file_type) != 1) { | ||||||
|  |         failf(data, "unable to set private key file\n"); | ||||||
|  |         return 0; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case SSL_FILETYPE_ENGINE: | ||||||
|  | #ifdef HAVE_OPENSSL_ENGINE_H | ||||||
|  |       {                         /* XXXX still needs some work */ | ||||||
|  |         EVP_PKEY *priv_key = NULL; | ||||||
|  |         if (conn && conn->data && conn->data->engine) { | ||||||
|  |           if (!key_file || !key_file[0]) { | ||||||
|  |             failf(data, "no key set to load from crypto engine\n"); | ||||||
|  |             return 0; | ||||||
|  |           } | ||||||
|  |           priv_key = ENGINE_load_private_key(conn->data->engine,key_file, | ||||||
|  |                                              data->set.key_passwd); | ||||||
|  |           if (!priv_key) { | ||||||
|  |             failf(data, "failed to load private key from crypto engine\n"); | ||||||
|  |             return 0; | ||||||
|  |           } | ||||||
|  |           if (SSL_CTX_use_PrivateKey(conn->ssl.ctx, priv_key) != 1) { | ||||||
|  |             failf(data, "unable to set private key\n"); | ||||||
|  |             EVP_PKEY_free(priv_key); | ||||||
|  |             return 0; | ||||||
|  |           } | ||||||
|  |           EVP_PKEY_free(priv_key);  /* we don't need the handle any more... */ | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |           failf(data, "crypto engine not set, can't load private key\n"); | ||||||
|  |           return 0; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | #else | ||||||
|  |       failf(data, "file type ENG for private key not supported\n"); | ||||||
|  |       return 0; | ||||||
|  | #endif | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       failf(data, "not supported file type for private key\n"); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|      |      | ||||||
|     ssl=SSL_new(conn->ssl.ctx); |     ssl=SSL_new(conn->ssl.ctx); | ||||||
|     x509=SSL_get_certificate(ssl); |     x509=SSL_get_certificate(ssl); | ||||||
| @@ -229,7 +332,7 @@ int cert_stuff(struct connectdata *conn, | |||||||
|     /* Now we know that a key and cert have been set against |     /* Now we know that a key and cert have been set against | ||||||
|      * the SSL context */ |      * the SSL context */ | ||||||
|     if (!SSL_CTX_check_private_key(conn->ssl.ctx)) { |     if (!SSL_CTX_check_private_key(conn->ssl.ctx)) { | ||||||
|       failf(data, "Private key does not match the certificate public key\n"); |       failf(data, "Private key does not match the certificate public key"); | ||||||
|       return(0); |       return(0); | ||||||
|     } |     } | ||||||
| #ifndef HAVE_USERDATA_IN_PWD_CALLBACK     | #ifndef HAVE_USERDATA_IN_PWD_CALLBACK     | ||||||
| @@ -257,6 +360,10 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx) | |||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
| /* "global" init done? */ | /* "global" init done? */ | ||||||
| static int init_ssl=0; | static int init_ssl=0; | ||||||
|  |  | ||||||
|  | /* we have the "SSL is seeded" boolean global for the application to | ||||||
|  |    prevent multiple time-consuming seedings in vain */ | ||||||
|  | static bool ssl_seeded = FALSE; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Global init */ | /* Global init */ | ||||||
| @@ -269,6 +376,10 @@ void Curl_SSL_init(void) | |||||||
|  |  | ||||||
|   init_ssl++; /* never again */ |   init_ssl++; /* never again */ | ||||||
|  |  | ||||||
|  | #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES | ||||||
|  |   ENGINE_load_builtin_engines(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   /* Lets get nice error messages */ |   /* Lets get nice error messages */ | ||||||
|   SSL_load_error_strings(); |   SSL_load_error_strings(); | ||||||
|  |  | ||||||
| @@ -292,6 +403,12 @@ void Curl_SSL_cleanup(void) | |||||||
|     /* EVP_cleanup() removes all ciphers and digests from the |     /* EVP_cleanup() removes all ciphers and digests from the | ||||||
|        table. */ |        table. */ | ||||||
|     EVP_cleanup(); |     EVP_cleanup(); | ||||||
|  |  | ||||||
|  | #ifdef HAVE_ENGINE_cleanup | ||||||
|  |     ENGINE_cleanup(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |     init_ssl=0; /* not inited any more */ | ||||||
|   } |   } | ||||||
| #else | #else | ||||||
|   /* SSL disabled, do nothing */ |   /* SSL disabled, do nothing */ | ||||||
| @@ -426,6 +543,13 @@ int Curl_SSL_Close_All(struct SessionHandle *data) | |||||||
|     /* free the cache data */ |     /* free the cache data */ | ||||||
|     free(data->state.session); |     free(data->state.session); | ||||||
|   } |   } | ||||||
|  | #ifdef HAVE_OPENSSL_ENGINE_H | ||||||
|  |   if (data->engine) | ||||||
|  |   { | ||||||
|  |     ENGINE_free(data->engine); | ||||||
|  |     data->engine = NULL; | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -435,23 +559,39 @@ int Curl_SSL_Close_All(struct SessionHandle *data) | |||||||
| static int Store_SSL_Session(struct connectdata *conn) | static int Store_SSL_Session(struct connectdata *conn) | ||||||
| { | { | ||||||
|   SSL_SESSION *ssl_sessionid; |   SSL_SESSION *ssl_sessionid; | ||||||
|   struct curl_ssl_session *store; |  | ||||||
|   int i; |   int i; | ||||||
|   struct SessionHandle *data=conn->data; /* the mother of all structs */ |   struct SessionHandle *data=conn->data; /* the mother of all structs */ | ||||||
|  |   struct curl_ssl_session *store = &data->state.session[0]; | ||||||
|   int oldest_age=data->state.session[0].age; /* zero if unused */ |   int oldest_age=data->state.session[0].age; /* zero if unused */ | ||||||
|  |  | ||||||
|   /* ask OpenSSL, say please */ |   /* ask OpenSSL, say please */ | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SSL_GET1_SESSION | ||||||
|   ssl_sessionid = SSL_get1_session(conn->ssl.handle); |   ssl_sessionid = SSL_get1_session(conn->ssl.handle); | ||||||
|  |  | ||||||
|   /* SSL_get1_session() will increment the reference |   /* SSL_get1_session() will increment the reference | ||||||
|      count and the session will stay in memory until explicitly freed with |      count and the session will stay in memory until explicitly freed with | ||||||
|      SSL_SESSION_free(3), regardless of its state. */ |      SSL_SESSION_free(3), regardless of its state.  | ||||||
|  |      This function was introduced in openssl 0.9.5a. */ | ||||||
|  | #else | ||||||
|  |   ssl_sessionid = SSL_get_session(conn->ssl.handle); | ||||||
|  |  | ||||||
|  |   /* if SSL_get1_session() is unavailable, use SSL_get_session(). | ||||||
|  |      This is an inferior option because the session can be flushed | ||||||
|  |      at any time by openssl. It is included only so curl compiles | ||||||
|  |      under versions of openssl < 0.9.5a. | ||||||
|  |       | ||||||
|  |      WARNING: How curl behaves if it's session is flushed is | ||||||
|  |      untested.  | ||||||
|  |   */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   /* Now we should add the session ID and the host name to the cache, (remove |   /* Now we should add the session ID and the host name to the cache, (remove | ||||||
|      the oldest if necessary) */ |      the oldest if necessary) */ | ||||||
|  |  | ||||||
|   /* find an empty slot for us, or find the oldest */ |   /* find an empty slot for us, or find the oldest */ | ||||||
|   for(i=0; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) { |   for(i=1; (i<data->set.ssl.numsessions) && | ||||||
|  |         data->state.session[i].sessionid; i++) { | ||||||
|     if(data->state.session[i].age < oldest_age) { |     if(data->state.session[i].age < oldest_age) { | ||||||
|       oldest_age = data->state.session[i].age; |       oldest_age = data->state.session[i].age; | ||||||
|       store = &data->state.session[i]; |       store = &data->state.session[i]; | ||||||
| @@ -538,17 +678,27 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|   /* mark this is being ssl enabled from here on out. */ |   /* mark this is being ssl enabled from here on out. */ | ||||||
|   conn->ssl.use = TRUE; |   conn->ssl.use = TRUE; | ||||||
|  |  | ||||||
|  |   if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) { | ||||||
|     /* Make funny stuff to get random input */ |     /* Make funny stuff to get random input */ | ||||||
|   random_the_seed(conn); |     random_the_seed(data); | ||||||
|  |  | ||||||
|  |     ssl_seeded = TRUE; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* check to see if we've been told to use an explicit SSL/TLS version */ | ||||||
|   switch(data->set.ssl.version) { |   switch(data->set.ssl.version) { | ||||||
|   default: |   default: | ||||||
|  |   case CURL_SSLVERSION_DEFAULT: | ||||||
|  |     /* we try to figure out version */ | ||||||
|     req_method = SSLv23_client_method(); |     req_method = SSLv23_client_method(); | ||||||
|     break; |     break; | ||||||
|   case 2: |   case CURL_SSLVERSION_TLSv1: | ||||||
|  |     req_method = TLSv1_client_method(); | ||||||
|  |     break; | ||||||
|  |   case CURL_SSLVERSION_SSLv2: | ||||||
|     req_method = SSLv2_client_method(); |     req_method = SSLv2_client_method(); | ||||||
|     break; |     break; | ||||||
|   case 3: |   case CURL_SSLVERSION_SSLv3: | ||||||
|     req_method = SSLv3_client_method(); |     req_method = SSLv3_client_method(); | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
| @@ -561,7 +711,11 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|   } |   } | ||||||
|      |      | ||||||
|   if(data->set.cert) { |   if(data->set.cert) { | ||||||
|     if (!cert_stuff(conn, data->set.cert, data->set.cert)) { |     if (!cert_stuff(conn, | ||||||
|  |                     data->set.cert, | ||||||
|  |                     data->set.cert_type, | ||||||
|  |                     data->set.key, | ||||||
|  |                     data->set.key_type)) { | ||||||
|       /* failf() is already done in cert_stuff() */ |       /* failf() is already done in cert_stuff() */ | ||||||
|       return CURLE_SSL_CONNECT_ERROR; |       return CURLE_SSL_CONNECT_ERROR; | ||||||
|     } |     } | ||||||
| @@ -570,7 +724,7 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|   if(data->set.ssl.cipher_list) { |   if(data->set.ssl.cipher_list) { | ||||||
|     if (!SSL_CTX_set_cipher_list(conn->ssl.ctx, |     if (!SSL_CTX_set_cipher_list(conn->ssl.ctx, | ||||||
|                                  data->set.ssl.cipher_list)) { |                                  data->set.ssl.cipher_list)) { | ||||||
|       failf(data, "failed setting cipher list\n"); |       failf(data, "failed setting cipher list"); | ||||||
|       return CURLE_SSL_CONNECT_ERROR; |       return CURLE_SSL_CONNECT_ERROR; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -583,7 +737,7 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|     if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, |     if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, | ||||||
|                                        data->set.ssl.CAfile, |                                        data->set.ssl.CAfile, | ||||||
|                                        data->set.ssl.CApath)) { |                                        data->set.ssl.CApath)) { | ||||||
|       failf(data,"error setting cerficate verify locations\n"); |       failf(data,"error setting cerficate verify locations"); | ||||||
|       return CURLE_SSL_CONNECT_ERROR; |       return CURLE_SSL_CONNECT_ERROR; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -610,8 +764,80 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|  |  | ||||||
|   /* pass the raw socket into the SSL layers */ |   /* pass the raw socket into the SSL layers */ | ||||||
|   SSL_set_fd(conn->ssl.handle, conn->firstsocket); |   SSL_set_fd(conn->ssl.handle, conn->firstsocket); | ||||||
|  |  | ||||||
|  |   do { | ||||||
|  |     int what; | ||||||
|  |     fd_set writefd; | ||||||
|  |     fd_set readfd; | ||||||
|  |     struct timeval interval; | ||||||
|  |     long timeout_ms; | ||||||
|  |  | ||||||
|     err = SSL_connect(conn->ssl.handle); |     err = SSL_connect(conn->ssl.handle); | ||||||
|  |  | ||||||
|  |     what = SSL_get_error(conn->ssl.handle, err); | ||||||
|  |  | ||||||
|  |     FD_ZERO(&writefd); | ||||||
|  |     FD_ZERO(&readfd); | ||||||
|  |  | ||||||
|  |     if(SSL_ERROR_WANT_READ == what) | ||||||
|  |       FD_SET(conn->firstsocket, &readfd); | ||||||
|  |     else if(SSL_ERROR_WANT_WRITE == what) | ||||||
|  |       FD_SET(conn->firstsocket, &writefd); | ||||||
|  |     else | ||||||
|  |       break; /* untreated error */ | ||||||
|  |  | ||||||
|  |     /* Find out if any timeout is set. If not, use 300 seconds. | ||||||
|  |        Otherwise, figure out the most strict timeout of the two possible one | ||||||
|  |        and then how much time that has elapsed to know how much time we | ||||||
|  |        allow for the connect call */ | ||||||
|  |     if(data->set.timeout || data->set.connecttimeout) { | ||||||
|  |       double has_passed; | ||||||
|  |  | ||||||
|  |       /* Evaluate in milliseconds how much time that has passed */ | ||||||
|  |       has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); | ||||||
|  |  | ||||||
|  | #ifndef min | ||||||
|  | #define min(a, b)   ((a) < (b) ? (a) : (b)) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |       /* get the most strict timeout of the ones converted to milliseconds */ | ||||||
|  |       if(data->set.timeout && | ||||||
|  |          (data->set.timeout>data->set.connecttimeout)) | ||||||
|  |         timeout_ms = data->set.timeout*1000; | ||||||
|  |       else | ||||||
|  |         timeout_ms = data->set.connecttimeout*1000; | ||||||
|  |        | ||||||
|  |       /* subtract the passed time */ | ||||||
|  |       timeout_ms -= (long)has_passed; | ||||||
|  |        | ||||||
|  |       if(timeout_ms < 0) { | ||||||
|  |         /* a precaution, no need to continue if time already is up */ | ||||||
|  |         failf(data, "SSL connection timeout"); | ||||||
|  |         return CURLE_OPERATION_TIMEOUTED; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       /* no particular time-out has been set */ | ||||||
|  |       timeout_ms=300000; /* milliseconds, default to five minutes */ | ||||||
|  |  | ||||||
|  |     interval.tv_sec = timeout_ms/1000; | ||||||
|  |     timeout_ms -= interval.tv_sec*1000; | ||||||
|  |  | ||||||
|  |     interval.tv_usec = timeout_ms*1000; | ||||||
|  |  | ||||||
|  |     what = select(conn->firstsocket+1, &readfd, &writefd, NULL, &interval); | ||||||
|  |     if(what > 0) | ||||||
|  |       /* reabable or writable, go loop yourself */ | ||||||
|  |       continue; | ||||||
|  |     else if(0 == what) { | ||||||
|  |       /* timeout */ | ||||||
|  |       failf(data, "SSL connection timeout"); | ||||||
|  |       return CURLE_OPERATION_TIMEOUTED; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       break; /* get out of loop */ | ||||||
|  |   } while(1); | ||||||
|  |  | ||||||
|   /* 1  is fine |   /* 1  is fine | ||||||
|      0  is "not successful but was shut down controlled" |      0  is "not successful but was shut down controlled" | ||||||
|      <0 is "handshake was not successful, because a fatal error occurred" */ |      <0 is "handshake was not successful, because a fatal error occurred" */ | ||||||
| @@ -705,7 +931,7 @@ Curl_SSLConnect(struct connectdata *conn) | |||||||
|   if(data->set.ssl.verifypeer) { |   if(data->set.ssl.verifypeer) { | ||||||
|     data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle); |     data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle); | ||||||
|     if (data->set.ssl.certverifyresult != X509_V_OK) { |     if (data->set.ssl.certverifyresult != X509_V_OK) { | ||||||
|       failf(data, "SSL certificate verify result: %d\n", |       failf(data, "SSL certificate verify result: %d", | ||||||
|             data->set.ssl.certverifyresult); |             data->set.ssl.certverifyresult); | ||||||
|       retcode = CURLE_SSL_PEER_CERTIFICATE; |       retcode = CURLE_SSL_PEER_CERTIFICATE; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ | |||||||
| #include "setup.h" | #include "setup.h" | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <ctype.h> | ||||||
|  |  | ||||||
| int curl_strequal(const char *first, const char *second) | int curl_strequal(const char *first, const char *second) | ||||||
| { | { | ||||||
| @@ -62,6 +63,9 @@ int curl_strnequal(const char *first, const char *second, size_t max) | |||||||
|     first++; |     first++; | ||||||
|     second++; |     second++; | ||||||
|   } |   } | ||||||
|  |   if(0 == max) | ||||||
|  |     return 1; /* they are equal this far */ | ||||||
|  |  | ||||||
|   return toupper(*first) == toupper(*second); |   return toupper(*first) == toupper(*second); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								lib/telnet.c
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								lib/telnet.c
									
									
									
									
									
								
							| @@ -226,9 +226,9 @@ static void printoption(struct SessionHandle *data, | |||||||
|     if (cmd == IAC) |     if (cmd == IAC) | ||||||
|     { |     { | ||||||
|       if (TELCMD_OK(option)) |       if (TELCMD_OK(option)) | ||||||
|         printf("%s IAC %s\n", direction, TELCMD(option)); |         Curl_infof(data, "%s IAC %s\n", direction, TELCMD(option)); | ||||||
|       else |       else | ||||||
|         printf("%s IAC %d\n", direction, option); |         Curl_infof(data, "%s IAC %d\n", direction, option); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
| @@ -244,12 +244,12 @@ static void printoption(struct SessionHandle *data, | |||||||
|           opt = NULL; |           opt = NULL; | ||||||
|  |  | ||||||
|         if(opt) |         if(opt) | ||||||
|           printf("%s %s %s\n", direction, fmt, opt); |           Curl_infof(data, "%s %s %s\n", direction, fmt, opt); | ||||||
|         else |         else | ||||||
|           printf("%s %s %d\n", direction, fmt, option); |           Curl_infof(data, "%s %s %d\n", direction, fmt, option); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|         printf("%s %d %d\n", direction, cmd, option); |         Curl_infof(data, "%s %d %d\n", direction, cmd, option); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -638,7 +638,7 @@ static void printsub(struct SessionHandle *data, | |||||||
|   { |   { | ||||||
|     if (direction) |     if (direction) | ||||||
|     { |     { | ||||||
|       printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT"); |       Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); | ||||||
|       if (length >= 3) |       if (length >= 3) | ||||||
|       { |       { | ||||||
|         int j; |         int j; | ||||||
| @@ -648,27 +648,27 @@ static void printsub(struct SessionHandle *data, | |||||||
|  |  | ||||||
|         if (i != IAC || j != SE) |         if (i != IAC || j != SE) | ||||||
|         { |         { | ||||||
|           printf("(terminated by "); |           Curl_infof(data, "(terminated by "); | ||||||
|           if (TELOPT_OK(i)) |           if (TELOPT_OK(i)) | ||||||
|             printf("%s ", TELOPT(i)); |             Curl_infof(data, "%s ", TELOPT(i)); | ||||||
|           else if (TELCMD_OK(i)) |           else if (TELCMD_OK(i)) | ||||||
|             printf("%s ", TELCMD(i)); |             Curl_infof(data, "%s ", TELCMD(i)); | ||||||
|           else |           else | ||||||
|             printf("%d ", i); |             Curl_infof(data, "%d ", i); | ||||||
|           if (TELOPT_OK(j)) |           if (TELOPT_OK(j)) | ||||||
|             printf("%s", TELOPT(j)); |             Curl_infof(data, "%s", TELOPT(j)); | ||||||
|           else if (TELCMD_OK(j)) |           else if (TELCMD_OK(j)) | ||||||
|             printf("%s", TELCMD(j)); |             Curl_infof(data, "%s", TELCMD(j)); | ||||||
|           else |           else | ||||||
|             printf("%d", j); |             Curl_infof(data, "%d", j); | ||||||
|           printf(", not IAC SE!) "); |           Curl_infof(data, ", not IAC SE!) "); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       length -= 2; |       length -= 2; | ||||||
|     } |     } | ||||||
|     if (length < 1) |     if (length < 1) | ||||||
|     { |     { | ||||||
|       printf("(Empty suboption?)"); |       Curl_infof(data, "(Empty suboption?)"); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -677,28 +677,28 @@ static void printsub(struct SessionHandle *data, | |||||||
|         case TELOPT_TTYPE: |         case TELOPT_TTYPE: | ||||||
|         case TELOPT_XDISPLOC: |         case TELOPT_XDISPLOC: | ||||||
|         case TELOPT_NEW_ENVIRON: |         case TELOPT_NEW_ENVIRON: | ||||||
|           printf("%s", TELOPT(pointer[0])); |           Curl_infof(data, "%s", TELOPT(pointer[0])); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           printf("%s (unsupported)", TELOPT(pointer[0])); |           Curl_infof(data, "%s (unsupported)", TELOPT(pointer[0])); | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|       printf("%d (unknown)", pointer[i]); |       Curl_infof(data, "%d (unknown)", pointer[i]); | ||||||
|  |  | ||||||
|     switch(pointer[1]) { |     switch(pointer[1]) { | ||||||
|       case TELQUAL_IS: |       case TELQUAL_IS: | ||||||
|         printf(" IS"); |         Curl_infof(data, " IS"); | ||||||
|         break; |         break; | ||||||
|       case TELQUAL_SEND: |       case TELQUAL_SEND: | ||||||
|         printf(" SEND"); |         Curl_infof(data, " SEND"); | ||||||
|         break; |         break; | ||||||
|       case TELQUAL_INFO: |       case TELQUAL_INFO: | ||||||
|         printf(" INFO/REPLY"); |         Curl_infof(data, " INFO/REPLY"); | ||||||
|         break; |         break; | ||||||
|       case TELQUAL_NAME: |       case TELQUAL_NAME: | ||||||
|         printf(" NAME"); |         Curl_infof(data, " NAME"); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|        |        | ||||||
| @@ -706,21 +706,21 @@ static void printsub(struct SessionHandle *data, | |||||||
|       case TELOPT_TTYPE: |       case TELOPT_TTYPE: | ||||||
|       case TELOPT_XDISPLOC: |       case TELOPT_XDISPLOC: | ||||||
|         pointer[length] = 0; |         pointer[length] = 0; | ||||||
|         printf(" \"%s\"", &pointer[2]); |         Curl_infof(data, " \"%s\"", &pointer[2]); | ||||||
|         break; |         break; | ||||||
|       case TELOPT_NEW_ENVIRON: |       case TELOPT_NEW_ENVIRON: | ||||||
|         if(pointer[1] == TELQUAL_IS) { |         if(pointer[1] == TELQUAL_IS) { | ||||||
|           printf(" "); |           Curl_infof(data, " "); | ||||||
|           for(i = 3;i < length;i++) { |           for(i = 3;i < length;i++) { | ||||||
|             switch(pointer[i]) { |             switch(pointer[i]) { | ||||||
|               case NEW_ENV_VAR: |               case NEW_ENV_VAR: | ||||||
|                 printf(", "); |                 Curl_infof(data, ", "); | ||||||
|                 break; |                 break; | ||||||
|               case NEW_ENV_VALUE: |               case NEW_ENV_VALUE: | ||||||
|                 printf(" = "); |                 Curl_infof(data, " = "); | ||||||
|                 break; |                 break; | ||||||
|               default: |               default: | ||||||
|                 printf("%c", pointer[i]); |                 Curl_infof(data, "%c", pointer[i]); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| @@ -728,13 +728,13 @@ static void printsub(struct SessionHandle *data, | |||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
|         for (i = 2; i < length; i++) |         for (i = 2; i < length; i++) | ||||||
|           printf(" %.2x", pointer[i]); |           Curl_infof(data, " %.2x", pointer[i]); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|        |        | ||||||
|     if (direction) |     if (direction) | ||||||
|     { |     { | ||||||
|       printf("\n"); |       Curl_infof(data, "\n"); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -1090,7 +1090,7 @@ CURLcode Curl_telnet(struct connectdata *conn) | |||||||
|       { |       { | ||||||
|         unsigned char outbuf[2]; |         unsigned char outbuf[2]; | ||||||
|         int out_count = 0; |         int out_count = 0; | ||||||
|         size_t bytes_written; |         ssize_t bytes_written; | ||||||
|         char *buffer = buf; |         char *buffer = buf; | ||||||
|                |                | ||||||
|         if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) { |         if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) { | ||||||
| @@ -1116,6 +1116,7 @@ CURLcode Curl_telnet(struct connectdata *conn) | |||||||
|         { |         { | ||||||
|           if(events.lNetworkEvents & FD_READ) |           if(events.lNetworkEvents & FD_READ) | ||||||
|           { |           { | ||||||
|  |             /* This reallu OUGHT to check its return code. */ | ||||||
|             Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); |             Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); | ||||||
|              |              | ||||||
|             telrcv(conn, (unsigned char *)buf, nread); |             telrcv(conn, (unsigned char *)buf, nread); | ||||||
| @@ -1142,7 +1143,7 @@ CURLcode Curl_telnet(struct connectdata *conn) | |||||||
| #else | #else | ||||||
|   FD_ZERO (&readfd);		/* clear it */ |   FD_ZERO (&readfd);		/* clear it */ | ||||||
|   FD_SET (sockfd, &readfd); |   FD_SET (sockfd, &readfd); | ||||||
|   FD_SET (1, &readfd); |   FD_SET (0, &readfd); | ||||||
|  |  | ||||||
|   keepfd = readfd; |   keepfd = readfd; | ||||||
|  |  | ||||||
| @@ -1156,13 +1157,13 @@ CURLcode Curl_telnet(struct connectdata *conn) | |||||||
|     case 0:			/* timeout */ |     case 0:			/* timeout */ | ||||||
|       break; |       break; | ||||||
|     default:			/* read! */ |     default:			/* read! */ | ||||||
|       if(FD_ISSET(1, &readfd)) { /* read from stdin */ |       if(FD_ISSET(0, &readfd)) { /* read from stdin */ | ||||||
|         unsigned char outbuf[2]; |         unsigned char outbuf[2]; | ||||||
|         int out_count = 0; |         int out_count = 0; | ||||||
|         size_t bytes_written; |         ssize_t bytes_written; | ||||||
|         char *buffer = buf; |         char *buffer = buf; | ||||||
|          |          | ||||||
|         nread = read(1, buf, 255); |         nread = read(0, buf, 255); | ||||||
|  |  | ||||||
|         while(nread--) { |         while(nread--) { | ||||||
|           outbuf[0] = *buffer++; |           outbuf[0] = *buffer++; | ||||||
| @@ -1176,6 +1177,7 @@ CURLcode Curl_telnet(struct connectdata *conn) | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       if(FD_ISSET(sockfd, &readfd)) { |       if(FD_ISSET(sockfd, &readfd)) { | ||||||
|  |         /* This OUGHT to check the return code... */ | ||||||
|         Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); |         Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); | ||||||
|  |  | ||||||
|         /* if we receive 0 or less here, the server closed the connection and |         /* if we receive 0 or less here, the server closed the connection and | ||||||
|   | |||||||
| @@ -69,10 +69,10 @@ struct timeval Curl_tvnow (void) | |||||||
|  * Make sure that the first argument is the more recent time, as otherwise |  * Make sure that the first argument is the more recent time, as otherwise | ||||||
|  * we'll get a weird negative time-diff back... |  * we'll get a weird negative time-diff back... | ||||||
|  */ |  */ | ||||||
| long Curl_tvdiff (struct timeval t1, struct timeval t2) | long Curl_tvdiff (struct timeval newer, struct timeval older) | ||||||
| { | { | ||||||
|   return (t1.tv_sec*1000 + t1.tv_usec/1000)- |   return (newer.tv_sec-older.tv_sec)*1000+ | ||||||
|     (t2.tv_sec*1000 + t2.tv_usec/1000); |     (499+newer.tv_usec-older.tv_usec)/1000; | ||||||
| } | } | ||||||
|  |  | ||||||
| long Curl_tvlong (struct timeval t1) | long Curl_tvlong (struct timeval t1) | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ struct timeval { | |||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| struct timeval Curl_tvnow (); | struct timeval Curl_tvnow (void); | ||||||
|  |  | ||||||
| /* the diff is from now on returned in number of milliseconds! */ | /* the diff is from now on returned in number of milliseconds! */ | ||||||
| long Curl_tvdiff (struct timeval t1, struct timeval t2); | long Curl_tvdiff (struct timeval t1, struct timeval t2); | ||||||
|   | |||||||
							
								
								
									
										891
									
								
								lib/transfer.c
									
									
									
									
									
								
							
							
						
						
									
										891
									
								
								lib/transfer.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -7,7 +7,7 @@ | |||||||
|  *                            | (__| |_| |  _ <| |___  |  *                            | (__| |_| |  _ <| |___  | ||||||
|  *                             \___|\___/|_| \_\_____| |  *                             \___|\___/|_| \_\_____| | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. |  * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. | ||||||
|  * |  * | ||||||
|  * In order to be useful for every potential user, curl and libcurl are |  * In order to be useful for every potential user, curl and libcurl are | ||||||
|  * dual-licensed under the MPL and the MIT/X-derivate licenses. |  * dual-licensed under the MPL and the MIT/X-derivate licenses. | ||||||
| @@ -24,6 +24,17 @@ | |||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| CURLcode Curl_perform(struct SessionHandle *data); | CURLcode Curl_perform(struct SessionHandle *data); | ||||||
|  |  | ||||||
|  | CURLcode Curl_pretransfer(struct SessionHandle *data); | ||||||
|  | CURLcode Curl_posttransfer(struct SessionHandle *data); | ||||||
|  |  | ||||||
|  | CURLcode Curl_readwrite(struct connectdata *conn, bool *done); | ||||||
|  | void Curl_single_fdset(struct connectdata *conn,  | ||||||
|  |                        fd_set *read_fd_set, | ||||||
|  |                        fd_set *write_fd_set, | ||||||
|  |                        fd_set *exc_fd_set, | ||||||
|  |                        int *max_fd); | ||||||
|  | CURLcode Curl_readwrite_init(struct connectdata *conn); | ||||||
|  |  | ||||||
| /* This sets up a forthcoming transfer */ | /* This sets up a forthcoming transfer */ | ||||||
| CURLcode  | CURLcode  | ||||||
| Curl_Transfer (struct connectdata *data, | Curl_Transfer (struct connectdata *data, | ||||||
|   | |||||||
							
								
								
									
										350
									
								
								lib/url.c
									
									
									
									
									
								
							
							
						
						
									
										350
									
								
								lib/url.c
									
									
									
									
									
								
							| @@ -72,7 +72,6 @@ | |||||||
| #include <inet.h> | #include <inet.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifndef HAVE_SELECT | #ifndef HAVE_SELECT | ||||||
| #error "We can't compile without select() support!" | #error "We can't compile without select() support!" | ||||||
| #endif | #endif | ||||||
| @@ -111,6 +110,10 @@ | |||||||
|  |  | ||||||
| #include <curl/types.h> | #include <curl/types.h> | ||||||
|  |  | ||||||
|  | #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) | ||||||
|  | #include "inet_ntoa_r.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define _MPRINTF_REPLACE /* use our functions only */ | #define _MPRINTF_REPLACE /* use our functions only */ | ||||||
| #include <curl/mprintf.h> | #include <curl/mprintf.h> | ||||||
|  |  | ||||||
| @@ -144,13 +147,23 @@ RETSIGTYPE alarmfunc(int signal) | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This is the internal function curl_easy_cleanup() calls. This should | ||||||
|  |  * cleanup and free all resources associated with this sessionhandle. | ||||||
|  |  * | ||||||
|  |  * NOTE: if we ever add something that attempts to write to a socket or | ||||||
|  |  * similar here, we must ignore SIGPIPE first. It is currently only done | ||||||
|  |  * when curl_easy_perform() is invoked. | ||||||
|  |  */ | ||||||
|  |  | ||||||
| CURLcode Curl_close(struct SessionHandle *data) | CURLcode Curl_close(struct SessionHandle *data) | ||||||
| { | { | ||||||
|   /* Loop through all open connections and kill them one by one */ |   /* Loop through all open connections and kill them one by one */ | ||||||
|   while(-1 != ConnectionKillOne(data)); |   while(-1 != ConnectionKillOne(data)); | ||||||
|  |  | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|   /* Close down all open info open SSL and sessions */ |   /* Close down all open SSL info and sessions */ | ||||||
|   Curl_SSL_Close_All(data); |   Curl_SSL_Close_All(data); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -178,6 +191,9 @@ CURLcode Curl_close(struct SessionHandle *data) | |||||||
|   /* free the connection cache */ |   /* free the connection cache */ | ||||||
|   free(data->state.connects); |   free(data->state.connects); | ||||||
|  |  | ||||||
|  |   if(data->info.contenttype) | ||||||
|  |     free(data->info.contenttype); | ||||||
|  |  | ||||||
|   free(data); |   free(data); | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
| @@ -200,10 +216,6 @@ CURLcode Curl_open(struct SessionHandle **curl) | |||||||
| { | { | ||||||
|   /* We don't yet support specifying the URL at this point */ |   /* We don't yet support specifying the URL at this point */ | ||||||
|   struct SessionHandle *data; |   struct SessionHandle *data; | ||||||
| #ifdef HAVE_SIGACTION |  | ||||||
|   struct sigaction sigact; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   /* Very simple start-up: alloc the struct, init it with zeroes and return */ |   /* Very simple start-up: alloc the struct, init it with zeroes and return */ | ||||||
|   data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle)); |   data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle)); | ||||||
|   if(!data) |   if(!data) | ||||||
| @@ -240,6 +252,9 @@ CURLcode Curl_open(struct SessionHandle **curl) | |||||||
|   data->state.current_speed = -1; /* init to negative == impossible */ |   data->state.current_speed = -1; /* init to negative == impossible */ | ||||||
|  |  | ||||||
|   data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */ |   data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */ | ||||||
|  |   data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */ | ||||||
|  |  | ||||||
|  |   data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ | ||||||
|    |    | ||||||
|   /* make libcurl quiet by default: */ |   /* make libcurl quiet by default: */ | ||||||
|   data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */ |   data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */ | ||||||
| @@ -263,31 +278,6 @@ CURLcode Curl_open(struct SessionHandle **curl) | |||||||
|  |  | ||||||
|   *curl = data; |   *curl = data; | ||||||
|  |  | ||||||
|   /************************************************************* |  | ||||||
|    * Set signal handler to catch SIGALRM |  | ||||||
|    *************************************************************/ |  | ||||||
| #ifdef HAVE_SIGACTION |  | ||||||
|   sigaction(SIGALRM, NULL, &sigact); |  | ||||||
|   sigact.sa_handler = alarmfunc; |  | ||||||
| #ifdef SA_RESTART |  | ||||||
|   /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ |  | ||||||
|   sigact.sa_flags &= ~SA_RESTART; |  | ||||||
| #endif |  | ||||||
|   sigaction(SIGALRM, &sigact, NULL); |  | ||||||
| #else |  | ||||||
|   /* no sigaction(), revert to the much lamer signal() */ |  | ||||||
| #ifdef HAVE_SIGNAL |  | ||||||
|   signal(SIGALRM, alarmfunc); |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   /************************************************************* |  | ||||||
|    * Tell signal handler to ignore SIGPIPE |  | ||||||
|    *************************************************************/ |  | ||||||
| #if defined(HAVE_SIGNAL) && defined(SIGPIPE) |  | ||||||
|   (void) signal(SIGPIPE, SIG_IGN); |  | ||||||
| #endif |  | ||||||
|    |  | ||||||
|   return CURLE_OK; |   return CURLE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -299,6 +289,19 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) | |||||||
|   va_start(param, option); |   va_start(param, option); | ||||||
|  |  | ||||||
|   switch(option) { |   switch(option) { | ||||||
|  |   case CURLOPT_DNS_CACHE_TIMEOUT: | ||||||
|  |     data->set.dns_cache_timeout = va_arg(param, int); | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_DNS_USE_GLOBAL_CACHE:  | ||||||
|  |     { | ||||||
|  |       int use_cache = va_arg(param, int); | ||||||
|  |       if (use_cache) { | ||||||
|  |         Curl_global_host_cache_init(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       data->set.global_dns_cache = use_cache; | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|   case CURLOPT_SSL_CIPHER_LIST: |   case CURLOPT_SSL_CIPHER_LIST: | ||||||
|     /* set a list of cipher we want to use in the SSL connection */ |     /* set a list of cipher we want to use in the SSL connection */ | ||||||
|     data->set.ssl.cipher_list = va_arg(param, char *); |     data->set.ssl.cipher_list = va_arg(param, char *); | ||||||
| @@ -543,6 +546,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) | |||||||
|     data->set.ftpport = va_arg(param, char *); |     data->set.ftpport = va_arg(param, char *); | ||||||
|     data->set.ftp_use_port = data->set.ftpport?1:0; |     data->set.ftp_use_port = data->set.ftpport?1:0; | ||||||
|     break; |     break; | ||||||
|  |  | ||||||
|  |   case CURLOPT_FTP_USE_EPSV: | ||||||
|  |     data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE; | ||||||
|  |     break; | ||||||
|  |  | ||||||
|   case CURLOPT_HTTPHEADER: |   case CURLOPT_HTTPHEADER: | ||||||
|     /* |     /* | ||||||
|      * Set a list with HTTP headers to use (or replace internals with) |      * Set a list with HTTP headers to use (or replace internals with) | ||||||
| @@ -554,8 +562,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) | |||||||
|      * Set a custom string to use as request |      * Set a custom string to use as request | ||||||
|      */ |      */ | ||||||
|     data->set.customrequest = va_arg(param, char *); |     data->set.customrequest = va_arg(param, char *); | ||||||
|     if(data->set.customrequest) |  | ||||||
|  |     /* we don't set | ||||||
|        data->set.httpreq = HTTPREQ_CUSTOM; |        data->set.httpreq = HTTPREQ_CUSTOM; | ||||||
|  |        here, we continue as if we were using the already set type | ||||||
|  |        and this just changes the actual request keyword */ | ||||||
|     break; |     break; | ||||||
|   case CURLOPT_HTTPPOST: |   case CURLOPT_HTTPPOST: | ||||||
|     /* |     /* | ||||||
| @@ -570,8 +581,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) | |||||||
|     /* |     /* | ||||||
|      * Set to force us do HTTP GET |      * Set to force us do HTTP GET | ||||||
|      */ |      */ | ||||||
|     if(va_arg(param, long)) |     if(va_arg(param, long)) { | ||||||
|       data->set.httpreq = HTTPREQ_GET; |       data->set.httpreq = HTTPREQ_GET; | ||||||
|  |       data->set.upload = FALSE; /* switch off upload */ | ||||||
|  |     } | ||||||
|     break; |     break; | ||||||
|  |  | ||||||
|   case CURLOPT_INFILE: |   case CURLOPT_INFILE: | ||||||
| @@ -802,11 +815,75 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) | |||||||
|      */ |      */ | ||||||
|     data->set.cert = va_arg(param, char *); |     data->set.cert = va_arg(param, char *); | ||||||
|     break; |     break; | ||||||
|   case CURLOPT_SSLCERTPASSWD: |   case CURLOPT_SSLCERTTYPE: | ||||||
|     /* |     /* | ||||||
|      * String that holds the SSL certificate password. |      * String that holds file type of the SSL certificate to use | ||||||
|      */ |      */ | ||||||
|     data->set.cert_passwd = va_arg(param, char *); |     data->set.cert_type = va_arg(param, char *); | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_SSLKEY: | ||||||
|  |     /* | ||||||
|  |      * String that holds file name of the SSL certificate to use | ||||||
|  |      */ | ||||||
|  |     data->set.key = va_arg(param, char *); | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_SSLKEYTYPE: | ||||||
|  |     /* | ||||||
|  |      * String that holds file type of the SSL certificate to use | ||||||
|  |      */ | ||||||
|  |     data->set.key_type = va_arg(param, char *); | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_SSLKEYPASSWD: | ||||||
|  |     /* | ||||||
|  |      * String that holds the SSL private key password. | ||||||
|  |      */ | ||||||
|  |     data->set.key_passwd = va_arg(param, char *); | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_SSLENGINE: | ||||||
|  |     /* | ||||||
|  |      * String that holds the SSL crypto engine. | ||||||
|  |      */ | ||||||
|  | #ifdef HAVE_OPENSSL_ENGINE_H | ||||||
|  |     { | ||||||
|  |       const char *cpTemp = va_arg(param, char *); | ||||||
|  |       ENGINE     *e; | ||||||
|  |       if (cpTemp && cpTemp[0]) { | ||||||
|  |         e = ENGINE_by_id(cpTemp); | ||||||
|  |         if (e) { | ||||||
|  |           if (data->engine) { | ||||||
|  |             ENGINE_free(data->engine); | ||||||
|  |           } | ||||||
|  |           data->engine = e; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |           failf(data, "SSL Engine '%s' not found", cpTemp); | ||||||
|  |           return CURLE_SSL_ENGINE_NOTFOUND; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | #else | ||||||
|  |     return CURLE_SSL_ENGINE_NOTFOUND; | ||||||
|  | #endif | ||||||
|  |     break; | ||||||
|  |   case CURLOPT_SSLENGINE_DEFAULT: | ||||||
|  |     /* | ||||||
|  |      * flag to set engine as default. | ||||||
|  |      */ | ||||||
|  | #ifdef HAVE_OPENSSL_ENGINE_H | ||||||
|  |     if (data->engine) { | ||||||
|  |       if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) { | ||||||
|  | #ifdef DEBUG | ||||||
|  |         fprintf(stderr,"set default crypto engine\n"); | ||||||
|  | #endif | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  | #ifdef DEBUG | ||||||
|  |         failf(data, "set default crypto engine failed"); | ||||||
|  | #endif | ||||||
|  |         return CURLE_SSL_ENGINE_SETFAILED; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|     break; |     break; | ||||||
|   case CURLOPT_CRLF: |   case CURLOPT_CRLF: | ||||||
|     /* |     /* | ||||||
| @@ -888,9 +965,6 @@ CURLcode Curl_disconnect(struct connectdata *conn) | |||||||
|   if(conn->proto.generic) |   if(conn->proto.generic) | ||||||
|     free(conn->proto.generic); |     free(conn->proto.generic); | ||||||
|  |  | ||||||
|   if(conn->hostent_buf) /* host name info */ |  | ||||||
|     Curl_freeaddrinfo(conn->hostent_buf); |  | ||||||
|  |  | ||||||
|   if(conn->newurl) |   if(conn->newurl) | ||||||
|     free(conn->newurl); |     free(conn->newurl); | ||||||
|  |  | ||||||
| @@ -957,9 +1031,9 @@ static bool SocketIsDead(int sock) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Given one filled in connection struct, this function should detect if there |  * Given one filled in connection struct (named needle), this function should | ||||||
|  * already is one that have all the significant details exactly the same and |  * detect if there already is one that have all the significant details | ||||||
|  * thus should be used instead. |  * exactly the same and thus should be used instead. | ||||||
|  */ |  */ | ||||||
| static bool | static bool | ||||||
| ConnectionExists(struct SessionHandle *data, | ConnectionExists(struct SessionHandle *data, | ||||||
| @@ -978,8 +1052,14 @@ ConnectionExists(struct SessionHandle *data, | |||||||
|     if(!check) |     if(!check) | ||||||
|       /* NULL pointer means not filled-in entry */ |       /* NULL pointer means not filled-in entry */ | ||||||
|       continue; |       continue; | ||||||
|     if(!needle->bits.httpproxy) { |     if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) { | ||||||
|       /* The requested connection does not use a HTTP proxy */ |       /* The requested connection does not use a HTTP proxy or it | ||||||
|  |          uses SSL. */ | ||||||
|  |  | ||||||
|  |       if(!(needle->protocol&PROT_SSL) && check->bits.httpproxy) | ||||||
|  |         /* we don't do SSL but the cached connection has a proxy, | ||||||
|  |            then don't match this */ | ||||||
|  |         continue; | ||||||
|  |  | ||||||
|       if(strequal(needle->protostr, check->protostr) && |       if(strequal(needle->protostr, check->protostr) && | ||||||
|          strequal(needle->name, check->name) && |          strequal(needle->name, check->name) && | ||||||
| @@ -1159,17 +1239,31 @@ static CURLcode ConnectPlease(struct connectdata *conn) | |||||||
| } | } | ||||||
|  |  | ||||||
| static CURLcode CreateConnection(struct SessionHandle *data, | static CURLcode CreateConnection(struct SessionHandle *data, | ||||||
|                                  struct connectdata **in_connect, |                                  struct connectdata **in_connect) | ||||||
|                                  bool allow_port) /* allow set.use_port? */ |  | ||||||
| { | { | ||||||
|   char *tmp; |   char *tmp; | ||||||
|   char *buf; |   char *buf; | ||||||
|   CURLcode result; |   CURLcode result=CURLE_OK; | ||||||
|   char resumerange[40]=""; |   char resumerange[40]=""; | ||||||
|   struct connectdata *conn; |   struct connectdata *conn; | ||||||
|   struct connectdata *conn_temp; |   struct connectdata *conn_temp; | ||||||
|   char endbracket; |   char endbracket; | ||||||
|   int urllen; |   int urllen; | ||||||
|  | #ifdef HAVE_INET_NTOA_R | ||||||
|  |   char ntoa_buf[64]; | ||||||
|  | #endif | ||||||
|  | #ifdef HAVE_ALARM | ||||||
|  |   unsigned int prev_alarm; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SIGACTION | ||||||
|  |   struct sigaction keep_sigact;   /* store the old struct here */ | ||||||
|  |   bool keep_copysig;              /* did copy it? */ | ||||||
|  | #else | ||||||
|  | #ifdef HAVE_SIGNAL | ||||||
|  |   void *keep_sigact;              /* store the old handler here */ | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
|    * Check input data |    * Check input data | ||||||
| @@ -1198,7 +1292,6 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|  |  | ||||||
|   /* and we setup a few fields in case we end up actually using this struct */ |   /* and we setup a few fields in case we end up actually using this struct */ | ||||||
|   conn->data = data;           /* remember our daddy */ |   conn->data = data;           /* remember our daddy */ | ||||||
|   conn->upload_bufsize = UPLOAD_BUFSIZE; /* default upload buffer size */ |  | ||||||
|   conn->firstsocket = -1;     /* no file descriptor */ |   conn->firstsocket = -1;     /* no file descriptor */ | ||||||
|   conn->secondarysocket = -1; /* no file descriptor */ |   conn->secondarysocket = -1; /* no file descriptor */ | ||||||
|   conn->connectindex = -1;    /* no index */ |   conn->connectindex = -1;    /* no index */ | ||||||
| @@ -1496,6 +1589,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|           /* we have a proxy here to set */ |           /* we have a proxy here to set */ | ||||||
|           data->change.proxy = proxy; |           data->change.proxy = proxy; | ||||||
|           data->change.proxy_alloc=TRUE; /* this needs to be freed later */ |           data->change.proxy_alloc=TRUE; /* this needs to be freed later */ | ||||||
|  |           conn->bits.httpproxy = TRUE; | ||||||
|         } |         } | ||||||
|       } /* if (!nope) - it wasn't specified non-proxy */ |       } /* if (!nope) - it wasn't specified non-proxy */ | ||||||
|     } /* NO_PROXY wasn't specified or '*' */ |     } /* NO_PROXY wasn't specified or '*' */ | ||||||
| @@ -1546,19 +1640,21 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|    *************************************************************/ |    *************************************************************/ | ||||||
|  |  | ||||||
|   if (strequal(conn->protostr, "HTTP")) { |   if (strequal(conn->protostr, "HTTP")) { | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTP; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_HTTP; | ||||||
|     conn->remote_port = PORT_HTTP; |     conn->remote_port = PORT_HTTP; | ||||||
|     conn->protocol |= PROT_HTTP; |     conn->protocol |= PROT_HTTP; | ||||||
|     conn->curl_do = Curl_http; |     conn->curl_do = Curl_http; | ||||||
|     conn->curl_done = Curl_http_done; |     conn->curl_done = Curl_http_done; | ||||||
|  |     conn->curl_connect = Curl_http_connect; | ||||||
|   } |   } | ||||||
|   else if (strequal(conn->protostr, "HTTPS")) { |   else if (strequal(conn->protostr, "HTTPS")) { | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|  |  | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_HTTPS; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_HTTPS; | ||||||
|     conn->remote_port = PORT_HTTPS; |     conn->remote_port = PORT_HTTPS; | ||||||
|     conn->protocol |= PROT_HTTP; |     conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL; | ||||||
|     conn->protocol |= PROT_HTTPS; |  | ||||||
|  |  | ||||||
|     conn->curl_do = Curl_http; |     conn->curl_do = Curl_http; | ||||||
|     conn->curl_done = Curl_http_done; |     conn->curl_done = Curl_http_done; | ||||||
| @@ -1571,7 +1667,8 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
| #endif /* !USE_SSLEAY */ | #endif /* !USE_SSLEAY */ | ||||||
|   } |   } | ||||||
|   else if (strequal(conn->protostr, "GOPHER")) { |   else if (strequal(conn->protostr, "GOPHER")) { | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_GOPHER; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_GOPHER; | ||||||
|     conn->remote_port = PORT_GOPHER; |     conn->remote_port = PORT_GOPHER; | ||||||
|     /* Skip /<item-type>/ in path if present */ |     /* Skip /<item-type>/ in path if present */ | ||||||
|     if (isdigit((int)conn->path[1])) { |     if (isdigit((int)conn->path[1])) { | ||||||
| @@ -1589,7 +1686,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|  |  | ||||||
|     if(strequal(conn->protostr, "FTPS")) { |     if(strequal(conn->protostr, "FTPS")) { | ||||||
| #ifdef USE_SSLEAY | #ifdef USE_SSLEAY | ||||||
|       conn->protocol |= PROT_FTPS; |       conn->protocol |= PROT_FTPS|PROT_SSL; | ||||||
| #else | #else | ||||||
|       failf(data, LIBCURL_NAME |       failf(data, LIBCURL_NAME | ||||||
|             " was built with SSL disabled, ftps: not supported!"); |             " was built with SSL disabled, ftps: not supported!"); | ||||||
| @@ -1597,7 +1694,8 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
| #endif /* !USE_SSLEAY */ | #endif /* !USE_SSLEAY */ | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_FTP; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_FTP; | ||||||
|     conn->remote_port = PORT_FTP; |     conn->remote_port = PORT_FTP; | ||||||
|     conn->protocol |= PROT_FTP; |     conn->protocol |= PROT_FTP; | ||||||
|  |  | ||||||
| @@ -1652,21 +1750,24 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|     /* telnet testing factory */ |     /* telnet testing factory */ | ||||||
|     conn->protocol |= PROT_TELNET; |     conn->protocol |= PROT_TELNET; | ||||||
|  |  | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port: PORT_TELNET; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port: PORT_TELNET; | ||||||
|     conn->remote_port = PORT_TELNET; |     conn->remote_port = PORT_TELNET; | ||||||
|     conn->curl_do = Curl_telnet; |     conn->curl_do = Curl_telnet; | ||||||
|     conn->curl_done = Curl_telnet_done; |     conn->curl_done = Curl_telnet_done; | ||||||
|   } |   } | ||||||
|   else if (strequal(conn->protostr, "DICT")) { |   else if (strequal(conn->protostr, "DICT")) { | ||||||
|     conn->protocol |= PROT_DICT; |     conn->protocol |= PROT_DICT; | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_DICT; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_DICT; | ||||||
|     conn->remote_port = PORT_DICT; |     conn->remote_port = PORT_DICT; | ||||||
|     conn->curl_do = Curl_dict; |     conn->curl_do = Curl_dict; | ||||||
|     conn->curl_done = NULL; /* no DICT-specific done */ |     conn->curl_done = NULL; /* no DICT-specific done */ | ||||||
|   } |   } | ||||||
|   else if (strequal(conn->protostr, "LDAP")) { |   else if (strequal(conn->protostr, "LDAP")) { | ||||||
|     conn->protocol |= PROT_LDAP; |     conn->protocol |= PROT_LDAP; | ||||||
|     conn->port = (data->set.use_port && allow_port)?data->set.use_port:PORT_LDAP; |     conn->port = (data->set.use_port && data->state.allow_port)? | ||||||
|  |       data->set.use_port:PORT_LDAP; | ||||||
|     conn->remote_port = PORT_LDAP; |     conn->remote_port = PORT_LDAP; | ||||||
|     conn->curl_do = Curl_ldap; |     conn->curl_do = Curl_ldap; | ||||||
|     conn->curl_done = NULL; /* no LDAP-specific done */ |     conn->curl_done = NULL; /* no LDAP-specific done */ | ||||||
| @@ -1883,6 +1984,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|  |  | ||||||
|     /* we need these pointers if we speak over a proxy */ |     /* we need these pointers if we speak over a proxy */ | ||||||
|     conn->hostname = old_conn->gname; |     conn->hostname = old_conn->gname; | ||||||
|  |     conn->name = old_conn->name; | ||||||
|  |  | ||||||
|     free(conn->path);    /* free the previously allocated path pointer */ |     free(conn->path);    /* free the previously allocated path pointer */ | ||||||
|  |  | ||||||
| @@ -1937,17 +2039,45 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|    * Set timeout if that is being used |    * Set timeout if that is being used | ||||||
|    *************************************************************/ |    *************************************************************/ | ||||||
|   if(data->set.timeout || data->set.connecttimeout) { |   if(data->set.timeout || data->set.connecttimeout) { | ||||||
|  |     /************************************************************* | ||||||
|  |      * Set signal handler to catch SIGALRM | ||||||
|  |      * Store the old value to be able to set it back later! | ||||||
|  |      *************************************************************/ | ||||||
|  |  | ||||||
|  | #ifdef HAVE_SIGACTION | ||||||
|  |     struct sigaction sigact; | ||||||
|  |     sigaction(SIGALRM, NULL, &sigact); | ||||||
|  |     keep_sigact = sigact; | ||||||
|  |     keep_copysig = TRUE; /* yes, we have a copy */ | ||||||
|  |     sigact.sa_handler = alarmfunc; | ||||||
|  | #ifdef SA_RESTART | ||||||
|  |     /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ | ||||||
|  |     sigact.sa_flags &= ~SA_RESTART; | ||||||
|  | #endif | ||||||
|  |     /* now set the new struct */ | ||||||
|  |     sigaction(SIGALRM, &sigact, NULL); | ||||||
|  | #else | ||||||
|  |     /* no sigaction(), revert to the much lamer signal() */ | ||||||
|  | #ifdef HAVE_SIGNAL | ||||||
|  |     keep_sigact = signal(SIGALRM, alarmfunc); | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     /* We set the timeout on the name resolving phase first, separately from |     /* We set the timeout on the name resolving phase first, separately from | ||||||
|      * the download/upload part to allow a maximum time on everything. This is |      * the download/upload part to allow a maximum time on everything. This is | ||||||
|      * a signal-based timeout, why it won't work and shouldn't be used in |      * a signal-based timeout, why it won't work and shouldn't be used in | ||||||
|      * multi-threaded environments. */ |      * multi-threaded environments. */ | ||||||
|  |  | ||||||
|     /* myalarm() makes a signal get sent when the timeout fires off, and that | #ifdef HAVE_ALARM | ||||||
|  |     /* alarm() makes a signal get sent when the timeout fires off, and that | ||||||
|        will abort system calls */ |        will abort system calls */ | ||||||
|     if(data->set.connecttimeout) |     prev_alarm = alarm(data->set.connecttimeout? | ||||||
|       myalarm(data->set.connecttimeout); |                        data->set.connecttimeout: | ||||||
|     else |                        data->set.timeout); | ||||||
|       myalarm(data->set.timeout); |     /* We can expect the conn->created time to be "now", as that was just | ||||||
|  |        recently set in the beginning of this function and nothing slow | ||||||
|  |        has been done since then until now. */ | ||||||
|  | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
| @@ -1961,12 +2091,13 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|     /* Resolve target host right on */ |     /* Resolve target host right on */ | ||||||
|     if(!conn->hostaddr) { |     if(!conn->hostaddr) { | ||||||
|       /* it might already be set if reusing a connection */ |       /* it might already be set if reusing a connection */ | ||||||
|       conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port, |       conn->hostaddr = Curl_resolv(data, conn->name, conn->port, | ||||||
|                                    &conn->hostent_buf); |                                    &conn->hostent_buf); | ||||||
|     } |     } | ||||||
|     if(!conn->hostaddr) { |     if(!conn->hostaddr) { | ||||||
|       failf(data, "Couldn't resolve host '%s'", conn->name); |       failf(data, "Couldn't resolve host '%s'", conn->name); | ||||||
|       return CURLE_COULDNT_RESOLVE_HOST; |       result =  CURLE_COULDNT_RESOLVE_HOST; | ||||||
|  |       /* don't return yet, we need to clean up the timeout first */ | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   else if(!conn->hostaddr) { |   else if(!conn->hostaddr) { | ||||||
| @@ -1975,18 +2106,57 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|  |  | ||||||
|     /* resolve proxy */ |     /* resolve proxy */ | ||||||
|     /* it might already be set if reusing a connection */ |     /* it might already be set if reusing a connection */ | ||||||
|     conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port, |     conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port, | ||||||
|                                  &conn->hostent_buf); |                                  &conn->hostent_buf); | ||||||
|  |  | ||||||
|     if(!conn->hostaddr) { |     if(!conn->hostaddr) { | ||||||
|       failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost); |       failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost); | ||||||
|       return CURLE_COULDNT_RESOLVE_PROXY; |       result = CURLE_COULDNT_RESOLVE_PROXY; | ||||||
|  |       /* don't return yet, we need to clean up the timeout first */ | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   Curl_pgrsTime(data, TIMER_NAMELOOKUP); |   Curl_pgrsTime(data, TIMER_NAMELOOKUP); | ||||||
|   if(data->set.timeout || data->set.connecttimeout) | #ifdef HAVE_ALARM | ||||||
|     /* switch off signal-based timeouts */ |   if(data->set.timeout || data->set.connecttimeout) { | ||||||
|     myalarm(0); | #ifdef HAVE_SIGACTION | ||||||
|  |     if(keep_copysig) { | ||||||
|  |       /* we got a struct as it looked before, now put that one back nice | ||||||
|  |          and clean */ | ||||||
|  |       sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ | ||||||
|  |     } | ||||||
|  | #else | ||||||
|  | #ifdef HAVE_SIGNAL | ||||||
|  |     /* restore the previous SIGALRM handler */ | ||||||
|  |     signal(SIGALRM, keep_sigact); | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |     /* switch back the alarm() to either zero or to what it was before minus | ||||||
|  |        the time we spent until now! */ | ||||||
|  |     if(prev_alarm) { | ||||||
|  |       /* there was an alarm() set before us, now put it back */ | ||||||
|  |       long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created); | ||||||
|  |       long alarm_set; | ||||||
|  |  | ||||||
|  |       /* the alarm period is counted in even number of seconds */ | ||||||
|  |       alarm_set = prev_alarm - elapsed_ms/1000; | ||||||
|  |  | ||||||
|  |       if(alarm_set<=0) { | ||||||
|  |         /* if it turned negative, we should fire off a SIGALRM here, but we | ||||||
|  |            won't, and zero would be to switch it off so we never set it to | ||||||
|  |            less than 1! */ | ||||||
|  |         alarm(1); | ||||||
|  |         result = CURLE_OPERATION_TIMEOUTED; | ||||||
|  |         failf(data, "Previous alarm fired off!"); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         alarm(alarm_set); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       alarm(0); /* just shut it off */ | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |   if(result) | ||||||
|  |     return result; | ||||||
|  |  | ||||||
|   /************************************************************* |   /************************************************************* | ||||||
|    * Proxy authentication |    * Proxy authentication | ||||||
| @@ -2072,7 +2242,12 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
|     struct in_addr in; |     struct in_addr in; | ||||||
|     (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); |     (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); | ||||||
|     infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name, |     infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name, | ||||||
|           inet_ntoa(in)); | #if defined(HAVE_INET_NTOA_R) | ||||||
|  |           inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)) | ||||||
|  | #else | ||||||
|  |           inet_ntoa(in) | ||||||
|  | #endif | ||||||
|  |           ); | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -2092,14 +2267,13 @@ static CURLcode CreateConnection(struct SessionHandle *data, | |||||||
| } | } | ||||||
|  |  | ||||||
| CURLcode Curl_connect(struct SessionHandle *data, | CURLcode Curl_connect(struct SessionHandle *data, | ||||||
|                       struct connectdata **in_connect, |                       struct connectdata **in_connect) | ||||||
|                       bool allow_port) |  | ||||||
| { | { | ||||||
|   CURLcode code; |   CURLcode code; | ||||||
|   struct connectdata *conn; |   struct connectdata *conn; | ||||||
|  |  | ||||||
|   /* call the stuff that needs to be called */ |   /* call the stuff that needs to be called */ | ||||||
|   code = CreateConnection(data, in_connect, allow_port); |   code = CreateConnection(data, in_connect); | ||||||
|  |  | ||||||
|   if(CURLE_OK != code) { |   if(CURLE_OK != code) { | ||||||
|     /* We're not allowed to return failure with memory left allocated |     /* We're not allowed to return failure with memory left allocated | ||||||
| @@ -2155,14 +2329,38 @@ CURLcode Curl_done(struct connectdata *conn) | |||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| CURLcode Curl_do(struct connectdata *conn) | CURLcode Curl_do(struct connectdata **connp) | ||||||
| { | { | ||||||
|   CURLcode result=CURLE_OK; |   CURLcode result=CURLE_OK; | ||||||
|  |   struct connectdata *conn = *connp; | ||||||
|  |   struct SessionHandle *data=conn->data; | ||||||
|  |  | ||||||
|   if(conn->curl_do) |   if(conn->curl_do) { | ||||||
|     /* generic protocol-specific function pointer set in curl_connect() */ |     /* generic protocol-specific function pointer set in curl_connect() */ | ||||||
|     result = conn->curl_do(conn); |     result = conn->curl_do(conn); | ||||||
|  |  | ||||||
|  |     /* This was formerly done in transfer.c, but we better do it here */ | ||||||
|  |      | ||||||
|  |     if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) { | ||||||
|  |       /* This was a re-use of a connection and we got a write error in the | ||||||
|  |        * DO-phase. Then we DISCONNECT this connection and have another attempt | ||||||
|  |        * to CONNECT and then DO again! The retry cannot possibly find another | ||||||
|  |        * connection to re-use, since we only keep one possible connection for | ||||||
|  |        * each.  */ | ||||||
|  |  | ||||||
|  |       infof(data, "Re-used connection seems dead, get a new one\n"); | ||||||
|  |  | ||||||
|  |       conn->bits.close = TRUE; /* enforce close of this connetion */ | ||||||
|  |       result = Curl_done(conn);   /* we are so done with this */ | ||||||
|  |       if(CURLE_OK == result) { | ||||||
|  |         /* Now, redo the connect and get a new connection */ | ||||||
|  |         result = Curl_connect(data, connp); | ||||||
|  |         if(CURLE_OK == result) | ||||||
|  |           /* ... finally back to actually retry the DO phase */ | ||||||
|  |           result = conn->curl_do(*connp); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user