Compare commits
300 Commits
curl-7_11_
...
curl-7_12_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39626d8cfd | ||
|
|
67ad29e716 | ||
|
|
8bbf9b13af | ||
|
|
cb21851c74 | ||
|
|
8d611bec6e | ||
|
|
1de1dc7314 | ||
|
|
aca79af7de | ||
|
|
da6eea9b38 | ||
|
|
dcf7310b2d | ||
|
|
c2e8ba0fba | ||
|
|
a5360255ba | ||
|
|
5690a2b493 | ||
|
|
ff0429a802 | ||
|
|
46cdc83b81 | ||
|
|
76dfef7117 | ||
|
|
de2aeb9fc2 | ||
|
|
17a5b44205 | ||
|
|
f99e347878 | ||
|
|
f5a0c17322 | ||
|
|
8442c3942d | ||
|
|
15cd35f67f | ||
|
|
459801d6e0 | ||
|
|
2c43d64302 | ||
|
|
fd802db39f | ||
|
|
765754d39d | ||
|
|
f7f6b288eb | ||
|
|
11ee9540bf | ||
|
|
f6319bd706 | ||
|
|
0912015a5c | ||
|
|
4e7575fc7a | ||
|
|
6531a6116d | ||
|
|
9a33561e80 | ||
|
|
88229a0f2a | ||
|
|
120394cc45 | ||
|
|
1adfe0fe18 | ||
|
|
d57c178a62 | ||
|
|
6faa83bc6a | ||
|
|
9fb4e019fa | ||
|
|
74551597b1 | ||
|
|
37c269d0ba | ||
|
|
5d8b526b80 | ||
|
|
83dcc3e061 | ||
|
|
4ed58463f7 | ||
|
|
85b2056dc7 | ||
|
|
94ca911dc1 | ||
|
|
24420c2191 | ||
|
|
59f904d8de | ||
|
|
755f98e768 | ||
|
|
aadc797225 | ||
|
|
5c882bdfa3 | ||
|
|
60f9450594 | ||
|
|
ff52ba7f7b | ||
|
|
0fbcea45d6 | ||
|
|
ca6d430561 | ||
|
|
91601b3bf4 | ||
|
|
cdd70596df | ||
|
|
7e186f9a63 | ||
|
|
a94e117ede | ||
|
|
662cb30372 | ||
|
|
bd3aba5d6a | ||
|
|
29ed6d24bf | ||
|
|
e2c5c20896 | ||
|
|
7c4b6cb0d9 | ||
|
|
aced2904ff | ||
|
|
17eb1fca7c | ||
|
|
2511d1193a | ||
|
|
e9056f5f95 | ||
|
|
a9893ca79a | ||
|
|
f39f7c28f0 | ||
|
|
a807065ccc | ||
|
|
67532e916c | ||
|
|
3920b4dae8 | ||
|
|
d70a335dce | ||
|
|
8001921112 | ||
|
|
d7cb09bd18 | ||
|
|
e11710714c | ||
|
|
5b0bfc298f | ||
|
|
0383f7f19d | ||
|
|
23a43c6e0f | ||
|
|
eb946690d2 | ||
|
|
c090fdbdf1 | ||
|
|
de279099e5 | ||
|
|
6bd8db3c99 | ||
|
|
6176f14141 | ||
|
|
512e54ff85 | ||
|
|
a5aa569fe3 | ||
|
|
e2e593a036 | ||
|
|
9ce0a7b49d | ||
|
|
4ab0d74250 | ||
|
|
b5f85ba77d | ||
|
|
b6ee33c6e1 | ||
|
|
1c69b15c7c | ||
|
|
54cd2bee58 | ||
|
|
5bf02b16a0 | ||
|
|
594cb8507b | ||
|
|
78aba6e4cd | ||
|
|
ccdcdb2a46 | ||
|
|
b121e41ec3 | ||
|
|
05d8e56ffd | ||
|
|
4345c7a712 | ||
|
|
12d5e33dc9 | ||
|
|
6d70a82757 | ||
|
|
47d52d4eca | ||
|
|
4973b0f88a | ||
|
|
d1542bf549 | ||
|
|
2b7727aad1 | ||
|
|
fd775454ca | ||
|
|
8e09a389c4 | ||
|
|
aa3ae01878 | ||
|
|
c123676825 | ||
|
|
d60c22572b | ||
|
|
1d7ce36791 | ||
|
|
34e8baab9a | ||
|
|
a219d774fe | ||
|
|
005042e973 | ||
|
|
d301d69fbf | ||
|
|
34af02caca | ||
|
|
91025d1dd6 | ||
|
|
c9bab31a7f | ||
|
|
2f60e91a9b | ||
|
|
018affe6d0 | ||
|
|
aeb27ccfdb | ||
|
|
939866faab | ||
|
|
98f968f2ee | ||
|
|
864f1a3366 | ||
|
|
f42b10242f | ||
|
|
853134017d | ||
|
|
d3999e06d1 | ||
|
|
0b0b37cffe | ||
|
|
a13f5888d5 | ||
|
|
c8807438ce | ||
|
|
3f106afd00 | ||
|
|
d925057e11 | ||
|
|
bbafb2eb27 | ||
|
|
434bc13812 | ||
|
|
5c592f7dd9 | ||
|
|
9bf1ba2f7e | ||
|
|
724e4a3585 | ||
|
|
f69711fc78 | ||
|
|
04e2520dbb | ||
|
|
7a35fb5403 | ||
|
|
63f97b38eb | ||
|
|
b8541929c8 | ||
|
|
329f17ac7c | ||
|
|
5dcab07c54 | ||
|
|
1f798affb9 | ||
|
|
a2ecdf4249 | ||
|
|
71fdc063bd | ||
|
|
887d78a9ad | ||
|
|
00557a5475 | ||
|
|
e18d27b78a | ||
|
|
228fea4628 | ||
|
|
e64dacb40e | ||
|
|
fff01f24bf | ||
|
|
e55dee3807 | ||
|
|
8c2ce33c0b | ||
|
|
135394f511 | ||
|
|
fe065dc851 | ||
|
|
445c7791a7 | ||
|
|
686ba84128 | ||
|
|
3394c01826 | ||
|
|
d67ea8c7ad | ||
|
|
535046430a | ||
|
|
9aebdff219 | ||
|
|
90da930131 | ||
|
|
fbdc1b1e3d | ||
|
|
e942df755b | ||
|
|
91c8be3628 | ||
|
|
d56c03840b | ||
|
|
d3d5cdf305 | ||
|
|
af43ce73e5 | ||
|
|
84b52e92f4 | ||
|
|
0aa7d11cc9 | ||
|
|
933f7cecae | ||
|
|
8e73e55336 | ||
|
|
55c015c136 | ||
|
|
bde6c6685e | ||
|
|
58387b91f9 | ||
|
|
6f74820cfc | ||
|
|
af72f198ba | ||
|
|
3fc831f9eb | ||
|
|
9f660862ec | ||
|
|
1354671c90 | ||
|
|
1175a226e3 | ||
|
|
358b72bb12 | ||
|
|
6c408c885a | ||
|
|
9cf04dff6a | ||
|
|
6bdcfecbcf | ||
|
|
3f21fe60fc | ||
|
|
b2c290e40e | ||
|
|
bc5b2fa12c | ||
|
|
32a9554c92 | ||
|
|
afc1ed60f7 | ||
|
|
91018f4f24 | ||
|
|
fb086b57a8 | ||
|
|
3fc39a6efb | ||
|
|
6062ac7c37 | ||
|
|
caf7854a3c | ||
|
|
6def0892ea | ||
|
|
1c0744bde6 | ||
|
|
7591e07b7c | ||
|
|
35ab93f484 | ||
|
|
dcf5e52b62 | ||
|
|
aae521d086 | ||
|
|
78e6508e22 | ||
|
|
4d9517f0b4 | ||
|
|
a331aa0221 | ||
|
|
679cabb532 | ||
|
|
7332350e85 | ||
|
|
69f4dda74a | ||
|
|
c19c3bd15a | ||
|
|
76ff92b811 | ||
|
|
4250637e7d | ||
|
|
08d1da106e | ||
|
|
9e31a0536e | ||
|
|
2960d37d71 | ||
|
|
c63af5fc01 | ||
|
|
fc6eff13b5 | ||
|
|
e7ee1ccf45 | ||
|
|
98bf69f8f1 | ||
|
|
0363fbc411 | ||
|
|
e3bc92ae53 | ||
|
|
27e76021e9 | ||
|
|
93dde29979 | ||
|
|
d42dcd60cd | ||
|
|
ade89799f5 | ||
|
|
6e118ce50f | ||
|
|
34be9df773 | ||
|
|
7356a67780 | ||
|
|
f77949ef3b | ||
|
|
26b8b3fc53 | ||
|
|
38cc79a54f | ||
|
|
ec113aefb9 | ||
|
|
913e1570bd | ||
|
|
e2aaf22d5d | ||
|
|
3304589043 | ||
|
|
0247642bb6 | ||
|
|
19f5aa165c | ||
|
|
1756499b11 | ||
|
|
15f9a93c25 | ||
|
|
e99287734b | ||
|
|
8349dde0f1 | ||
|
|
59907ebc0e | ||
|
|
da91d6ac66 | ||
|
|
7548115a0e | ||
|
|
8ca37dd1c7 | ||
|
|
31e9e4bb76 | ||
|
|
84a322ab23 | ||
|
|
707f217b2d | ||
|
|
e6b45a66ec | ||
|
|
b34c40dcf5 | ||
|
|
699ebe2f0b | ||
|
|
e1c6f216c2 | ||
|
|
630b73bfa8 | ||
|
|
877f16e5a5 | ||
|
|
fbe1fa9dcc | ||
|
|
5b65cc55a2 | ||
|
|
97769737d0 | ||
|
|
5b0a5c4050 | ||
|
|
4b9f8e766d | ||
|
|
96002646f1 | ||
|
|
5ef6904ec3 | ||
|
|
2f53da5e7a | ||
|
|
58f1cc0b5f | ||
|
|
98c70b73f2 | ||
|
|
6bd02a3ab5 | ||
|
|
372e7a6cd4 | ||
|
|
211004bb0d | ||
|
|
80d2fff1a1 | ||
|
|
cf3cf413c8 | ||
|
|
e218811ca3 | ||
|
|
a9f2274bd8 | ||
|
|
92179ff990 | ||
|
|
4aac210a83 | ||
|
|
245e3122df | ||
|
|
ffc5fa3a2b | ||
|
|
f5042cce34 | ||
|
|
712c67b4ae | ||
|
|
5dcfb8ad66 | ||
|
|
673ff5eb2c | ||
|
|
92fc3f07ba | ||
|
|
cff90cf3f9 | ||
|
|
a33c53a36b | ||
|
|
2370d4fa02 | ||
|
|
f128d904a5 | ||
|
|
fb1039f2ab | ||
|
|
923ce98e42 | ||
|
|
8e935b58a2 | ||
|
|
c93e972543 | ||
|
|
1cb66f5262 | ||
|
|
648e82f05d | ||
|
|
1dbe60b8b7 | ||
|
|
9631fa7407 | ||
|
|
9befc682ee | ||
|
|
fbeb674479 | ||
|
|
af641d20a7 | ||
|
|
d02587750c | ||
|
|
241a4b3d45 | ||
|
|
496e81a25a | ||
|
|
f39b081253 |
275
CHANGES
275
CHANGES
@@ -1,11 +1,278 @@
|
|||||||
_ _ ____ _
|
_ _ ____ _
|
||||||
___| | | | _ \| |
|
___| | | | _ \| |
|
||||||
/ __| | | | |_) | |
|
/ __| | | | |_) | |
|
||||||
| (__| |_| | _ <| |___
|
| (__| |_| | _ <| |___
|
||||||
\___|\___/|_| \_\_____|
|
\___|\___/|_| \_\_____|
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Version 7.12.0 (2 June 2004)
|
||||||
|
|
||||||
|
Daniel (1 June 2004)
|
||||||
|
- I clarified the --create-dirs option somewhat in the curl man page.
|
||||||
|
|
||||||
|
- Renaud Duhaut corrected the curl_unescape man page.
|
||||||
|
|
||||||
|
- David Byron modified one of Massimiliano Ziccardi's recent MSVC makefile
|
||||||
|
changes to now again use the mm lib by default.
|
||||||
|
|
||||||
|
Daniel (26 May 2004)
|
||||||
|
- Mohun Biswas added release-zlib and debug-zlib targets to the MSVC libcurl
|
||||||
|
Makefile
|
||||||
|
|
||||||
|
- David Byron reported a problem with proxy authentication when doing CONNECT,
|
||||||
|
like when accessing HTTPS sites wiht a proxy. This probably broke when I
|
||||||
|
rewrote the auth stuff recently.
|
||||||
|
|
||||||
|
- I added fileupload.c in the examples directory, showing how an upload to a
|
||||||
|
file:// URL is made.
|
||||||
|
|
||||||
|
Daniel (25 May 2004)
|
||||||
|
- Massimiliano Ziccardi updated the MSVC makefiles.
|
||||||
|
|
||||||
|
Daniel (24 May 2004)
|
||||||
|
- libcurl now supports "uploading" to file:// URLs. Test 204 and 205 were
|
||||||
|
added to verify.
|
||||||
|
|
||||||
|
- Simon Josefsson added a idn_free() function in libidn 0.4.5 as a reaction to
|
||||||
|
Gisle's previous mail. We now use this function, and thus we require libidn
|
||||||
|
0.4.5 or later. No earlier version will do.
|
||||||
|
|
||||||
|
- Robert D. Young reported that CURLOPT_COOKIEFILE and CURLOPT_COOKIE could
|
||||||
|
not be used both in one request. Fixed it and added test case 172 to verify.
|
||||||
|
|
||||||
|
Daniel (21 May 2004)
|
||||||
|
- While talking to host a.b.c, libcurl did wrongly not accept cookies that
|
||||||
|
were set to the domain .a.b.c (that is with a dot prefix). This is now fixed
|
||||||
|
and test case 171 verifies it.
|
||||||
|
|
||||||
|
Daniel (20 May 2004)
|
||||||
|
- Jesse Noller reported that the upload speed info reported by libcurl was
|
||||||
|
wrong. The same was true for the download speed. Fixed now.
|
||||||
|
|
||||||
|
Daniel (19 May 2004)
|
||||||
|
- David Byron added test case 170 - this used to crash the previous version of
|
||||||
|
curl.
|
||||||
|
|
||||||
|
Daniel (17 May 2004)
|
||||||
|
- Peter Sylvester's patch that addresses two flaws in the peer certificate
|
||||||
|
name verification:
|
||||||
|
o when multiple common names are used (as in the curl tests), the last name
|
||||||
|
needs to be selected.
|
||||||
|
o allow comparing with encoded values, at least with BMP and ISO latin1
|
||||||
|
encoded T61strings.
|
||||||
|
|
||||||
|
- All 191 test cases run through the torture test OK! 'make test-torture' is
|
||||||
|
now available in the root makefile (on configure-based environments).
|
||||||
|
|
||||||
|
Daniel (14 May 2004)
|
||||||
|
- With a slightly modified ftpserver.pl I've now run almost all tests through
|
||||||
|
with runtests.pl -t. This is goodness!
|
||||||
|
|
||||||
|
- Since I have been unable to contact the CVS admins for several months, I've
|
||||||
|
decided that the current CVS hosting was not good enough. I've now moved the
|
||||||
|
CVS repo once again, see README for updated cvs checkout instructions.
|
||||||
|
|
||||||
|
Daniel (13 May 2004)
|
||||||
|
- runtests.pl -t now runs fine all the way to test 100. I believe test case
|
||||||
|
100 fails because of an FTP server problem.
|
||||||
|
|
||||||
|
Daniel (12 May 2004)
|
||||||
|
- General cleanups all over to make libcurl survive and do well when a memory
|
||||||
|
function returns NULL. runtests.pl -t now works fine for the first 26 test
|
||||||
|
cases.
|
||||||
|
|
||||||
|
Daniel (11 May 2004)
|
||||||
|
- Seshubabu Pasam provided a patch that introduces curl_global_init_mem() -
|
||||||
|
like normal curl_global_init() but allows the app to replace all memory
|
||||||
|
functions with its own set. I modified it slightly.
|
||||||
|
|
||||||
|
- Based on Luca Alteas' comments, I modified the curllib.dsp generation code.
|
||||||
|
|
||||||
|
Daniel (10 May 2004)
|
||||||
|
- Gisle mailed Simon Josefsson (of libidn fame) about the benefits of a
|
||||||
|
separate free()-function by that lib to make sure the memory is freed by the
|
||||||
|
same memory subsystem that allocated it. He responded positively and this
|
||||||
|
will likely cause us to require a newer version of libidn as soon as Simon
|
||||||
|
releases one with such a libidn_free() function.
|
||||||
|
|
||||||
|
- James Bursa made runtests.pl's -t option work for any given test case, and I
|
||||||
|
edited to allow -g too. Not even test case 1 worked...
|
||||||
|
|
||||||
|
- Luca Altea made the nc= field not use quotes in outgoing HTTP Digest headers.
|
||||||
|
|
||||||
|
- Andr<64>s Garc<72>a fixed a problem in the test script that made it fail to
|
||||||
|
recognize our own running HTTP server.
|
||||||
|
|
||||||
|
Daniel (7 May 2004)
|
||||||
|
- James Bursa fixed the memanalyze.pl script to conder malloc(0) areas OK to
|
||||||
|
free() and he made two failed-resolve error messages use the new display-
|
||||||
|
name instead of the internally-used name.
|
||||||
|
|
||||||
|
- Gisle Vanem tried curl with
|
||||||
|
www.etdomenenavnkanmaksimaltinneholdesekstitrebokstaversliksomdette.com
|
||||||
|
which caused problems, and I fixed the single zero byte buffer overwrite
|
||||||
|
that occurred (due to a stupid protocol buffer size and parser).
|
||||||
|
|
||||||
|
- Made the lib/curllib.dsp file get generated automaticly when a distribution
|
||||||
|
package is made, with the msvcproj.* files as templates and all
|
||||||
|
win32-sources added. I think this can be made to work better than the always
|
||||||
|
lagging-behind previous approach. I'm not sure this builds a working project
|
||||||
|
file right now though!
|
||||||
|
|
||||||
|
Daniel (6 May 2004)
|
||||||
|
- Michael Benedict brought a fix that fills in the errorbuffer properly when
|
||||||
|
ares fails to resolve a name for a case not previously dealt with like this.
|
||||||
|
|
||||||
|
Daniel (5 May 2004)
|
||||||
|
- Joe Halpin fixed the annoying typecast warning in lib/ldap.c
|
||||||
|
|
||||||
|
- Gisle Vanem fixes:
|
||||||
|
o memdebug to not access NULL on several places
|
||||||
|
o libcurl.def; curl_formparse is gone.
|
||||||
|
o progress.c; fixed the percent values being trunced to 0.
|
||||||
|
o if2ip.*; constified the 'interface' argument.
|
||||||
|
|
||||||
|
- Tor Arntsen reported that many of his autobuilds froze and I found and fixed
|
||||||
|
a problem introduced with the HTTP auth overhaul that could lead to a
|
||||||
|
never-ending internal request-loop due to un-initialized variables!
|
||||||
|
|
||||||
|
- Removed several compiler warnings on various compilers/platforms.
|
||||||
|
|
||||||
|
Daniel (4 May 2004)
|
||||||
|
- curl_formparse() has been removed from the library. It has been marked and
|
||||||
|
mentioned as deprecated for several years.
|
||||||
|
|
||||||
|
Daniel (3 May 2004)
|
||||||
|
- Rewritten HTTP authentication code. The previous code could not properly
|
||||||
|
deal with the added test cases 167, 168 and 169. I've now rewritten the code
|
||||||
|
to better separate host and proxy authentication and not re-use the same
|
||||||
|
variables as much as before as it proved non working in the more involved
|
||||||
|
cases. All the current tests run OK now, and so do the new ones. The curl
|
||||||
|
tool got a new option named --proxy-digest to enable HTTP Digest
|
||||||
|
authentication with the proxy. I also made the library support it.
|
||||||
|
|
||||||
|
- Gisle Vanem made the LDAP code work with wldap32.dll as supplied with
|
||||||
|
Win-98/ME/2000/XP, so no extra .dlls are required when curl/libcurl is used
|
||||||
|
on these Windows versions.
|
||||||
|
|
||||||
|
Daniel (30 April 2004)
|
||||||
|
- runtests.pl now scans the valgrind log for valgrind-detected memory leaks
|
||||||
|
after each test case if valgrind was found and used.
|
||||||
|
|
||||||
|
- I modified the app-code in curl to include the new lib/curlx.h and only
|
||||||
|
access those functions using the curlx_-prefix in preparation for the future
|
||||||
|
removal of several curl_-functions from the public libcurl API.
|
||||||
|
|
||||||
|
- Introduced lib/curlx.h as a single header to provide the curlx_-functions
|
||||||
|
to apps.
|
||||||
|
|
||||||
|
- Added notices in the man pages for curl_getenv, curl_mprintf, curl_strequal
|
||||||
|
and curl_strnequal that they are subject for removal in a future release.
|
||||||
|
STOP USING THESE FUNCTIONS.
|
||||||
|
|
||||||
|
- Mihai Ionescu noticed he couldn't do formposts with whitespace in the file
|
||||||
|
names and yes, I broke that on April 23. Sigh. I fixed it now and added
|
||||||
|
test case 166 to verify it.
|
||||||
|
|
||||||
|
- Luca Altea pointed out a mistake left from the Digest patch of yesterday.
|
||||||
|
|
||||||
|
Daniel (29 April 2004)
|
||||||
|
- Made IDN domains work when sending requsts over HTTP proxy as well. Added
|
||||||
|
test case 165 to verify the functionality.
|
||||||
|
|
||||||
|
- Fixed a bug in the new internal host name setup when re-using connections.
|
||||||
|
|
||||||
|
- James Bursa found out that curl_easy_duphandle() with ares-built libcurl
|
||||||
|
created a bad handle that would crash in the first name resolve attempt. This
|
||||||
|
is now fixed and test case 512 was added to verify it.
|
||||||
|
|
||||||
|
- Luca Altea provided a major HTTP Digest code fix and cleanup. We now follow
|
||||||
|
the Digest RFC a lot better.
|
||||||
|
|
||||||
|
- Gisle Vanem made the SSL code use ERR_error_string_n() where applicable.
|
||||||
|
|
||||||
|
Daniel (27 April 2004)
|
||||||
|
- I remodeled Gisle's IDN code slightly and now we convert both the host name
|
||||||
|
and proxy name to the ACE encoded version to use internally for resolves and
|
||||||
|
cookies etc. They are now using one 'struct hostname' each that keep both
|
||||||
|
the original name and the possibly encoded name. IDN resolves work for me
|
||||||
|
now using ipv6, ipv4 and ares resolving. Even cookies on IDN sites seem to
|
||||||
|
do right. I got some failures at first when CHARSET wasn't set at all which
|
||||||
|
confused libidn completely and it decided by encoding of choice was
|
||||||
|
'ANSI_X3.4-1968'...
|
||||||
|
|
||||||
|
- made 'configure --without-libidn' work
|
||||||
|
|
||||||
|
Daniel (25 April 2004)
|
||||||
|
- Fixed the src/hugehelp.c file to include "setup.h" instead of "config.h" to
|
||||||
|
make the problems with USE_MANUAL on windows go away.
|
||||||
|
|
||||||
|
- configure --without-ssl could still wrongly include some OpenSSL info in the
|
||||||
|
Makefiles if pkg-config had info about OpenSSL. Bug #941762 reported by
|
||||||
|
Martin.
|
||||||
|
|
||||||
|
- Since we can now build and use quite a large set of 3rd party libraries, I
|
||||||
|
decided I would make configure produce a summary at the end showing what
|
||||||
|
libraries it uses and if not, what option to use to make it use that. I also
|
||||||
|
added some other random info that is nice in a "configure summary" output.
|
||||||
|
|
||||||
|
- Applied TommyTam's patch that now make curl work with telnet and stdin
|
||||||
|
properly on Windows.
|
||||||
|
|
||||||
|
- The changes for today below were made by me and Gisle Vanem.
|
||||||
|
|
||||||
|
The file previously known as hostip.c has now undergone a huge cleanup and
|
||||||
|
split:
|
||||||
|
|
||||||
|
hostip.c explained
|
||||||
|
==================
|
||||||
|
|
||||||
|
The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
|
||||||
|
source file are these:
|
||||||
|
|
||||||
|
CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
|
||||||
|
that. The host may not be able to resolve IPv6, but we don't really have to
|
||||||
|
take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4
|
||||||
|
defined.
|
||||||
|
|
||||||
|
CURLRES_ARES - is defined if libcurl is built to use c-ares for asynchronous
|
||||||
|
name resolves. It cannot have ENABLE_IPV6 defined at the same time, as
|
||||||
|
c-ares has no ipv6 support. This can be Windows or *nix.
|
||||||
|
|
||||||
|
CURLRES_THREADED - is defined if libcurl is built to run under (native)
|
||||||
|
Windows, and then the name resolve will be done in a new thread, and the
|
||||||
|
supported asynch API will be the same as for ares-builds.
|
||||||
|
|
||||||
|
If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
|
||||||
|
libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
|
||||||
|
defined.
|
||||||
|
|
||||||
|
The host*.c sources files are split up like this:
|
||||||
|
|
||||||
|
hostip.c - method-independent resolver functions and utility functions
|
||||||
|
hostasyn.c - functions for asynchronous name resolves
|
||||||
|
hostsyn.c - functions for synchronous name resolves
|
||||||
|
hostares.c - functions for ares-using name resolves
|
||||||
|
hostthre.c - functions for threaded name resolves
|
||||||
|
hostip4.c - ipv4-specific functions
|
||||||
|
hostip6.c - ipv6-specific functions
|
||||||
|
|
||||||
|
The hostip.h is the single united header file for all this. It defines the
|
||||||
|
CURLRES_* defines based on the config*.h and setup.h defines.
|
||||||
|
|
||||||
|
- Added function header comments to many functions in an attempt to better
|
||||||
|
explain the purpose of them all.
|
||||||
|
|
||||||
|
- configure --with-libidn is now supported. It makes the configure script
|
||||||
|
check for libidn libs and include files in the prefix path given. If you
|
||||||
|
say --with-libidn=/usr/local, it will check for the lib in /usr/local/lib
|
||||||
|
and the includes in /usr/local/include etc.
|
||||||
|
|
||||||
|
- curl_version_info() now returns a struct aged CURLVERSION_THIRD including
|
||||||
|
libidn version info. The string curl_version() returns also includes libidn
|
||||||
|
version info, if available.
|
||||||
|
|
||||||
Version 7.11.2 (26 April 2004)
|
Version 7.11.2 (26 April 2004)
|
||||||
|
|
||||||
Daniel (25 April 2004)
|
Daniel (25 April 2004)
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ test:
|
|||||||
test-full:
|
test-full:
|
||||||
@(cd tests; $(MAKE) all full-test)
|
@(cd tests; $(MAKE) all full-test)
|
||||||
|
|
||||||
|
test-torture:
|
||||||
|
@(cd tests; $(MAKE) all torture-test)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build source and binary rpms. For rpm-3.0 and above, the ~/.rpmmacros
|
# Build source and binary rpms. For rpm-3.0 and above, the ~/.rpmmacros
|
||||||
# must contain the following line:
|
# must contain the following line:
|
||||||
|
|||||||
15
README
15
README
@@ -17,7 +17,9 @@ README
|
|||||||
|
|
||||||
You find answers to the most frequent questions we get in the FAQ document.
|
You find answers to the most frequent questions we get in the FAQ document.
|
||||||
|
|
||||||
Study the COPYING file for distribution terms and similar.
|
Study the COPYING file for distribution terms and similar. If you distribute
|
||||||
|
curl binaries or other binaries that involve libcurl, you might enjoy the
|
||||||
|
LICENSE-MIXING document.
|
||||||
|
|
||||||
CONTACT
|
CONTACT
|
||||||
|
|
||||||
@@ -50,6 +52,7 @@ DOWNLOAD
|
|||||||
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
|
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
|
||||||
Germany -- http://curl.mirror.at.stealer.net/download.html
|
Germany -- http://curl.mirror.at.stealer.net/download.html
|
||||||
Germany -- http://curl.netmirror.org/download.html
|
Germany -- http://curl.netmirror.org/download.html
|
||||||
|
Germany -- http://www.mirrorspace.org/curl/
|
||||||
Hongkong -- http://www.execve.net/curl/
|
Hongkong -- http://www.execve.net/curl/
|
||||||
Russia -- http://curl.tsuren.net/download.html
|
Russia -- http://curl.tsuren.net/download.html
|
||||||
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
|
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
|
||||||
@@ -61,18 +64,14 @@ CVS
|
|||||||
|
|
||||||
To download the very latest source off the CVS server do this:
|
To download the very latest source off the CVS server do this:
|
||||||
|
|
||||||
cvs -d :pserver:cvsread@cvs.php.net:/repository login
|
cvs -d :pserver:anonymous@cool.haxx.se:/cvsroot/curl login
|
||||||
|
|
||||||
(enter "phpfi" when asked for password)
|
(just press enter when asked for password)
|
||||||
|
|
||||||
cvs -d :pserver:cvsread@cvs.php.net:/repository co curl
|
cvs -d :pserver:anonymous@cool.haxx.se:/cvsroot/curl co curl
|
||||||
|
|
||||||
(you'll get a directory named curl created, filled with the source code)
|
(you'll get a directory named curl created, filled with the source code)
|
||||||
|
|
||||||
cvs -d :pserver:cvsread@cvs.php.net:/repository logout
|
|
||||||
|
|
||||||
(you're off the hook!)
|
|
||||||
|
|
||||||
NOTICE
|
NOTICE
|
||||||
|
|
||||||
Curl contains pieces of source code that is Copyright (c) 1998, 1999
|
Curl contains pieces of source code that is Copyright (c) 1998, 1999
|
||||||
|
|||||||
102
RELEASE-NOTES
102
RELEASE-NOTES
@@ -1,74 +1,62 @@
|
|||||||
Curl and libcurl 7.11.2. A bugfix release.
|
Curl and libcurl 7.12.0.
|
||||||
|
|
||||||
Public curl release number: 80
|
Public curl release number: 81
|
||||||
Releases counted from the very beginning: 107
|
Releases counted from the very beginning: 108
|
||||||
Available command line options: 94
|
Available command line options: 96
|
||||||
Available curl_easy_setopt() options: 113
|
Available curl_easy_setopt() options: 113
|
||||||
|
Number of public functions in libcurl: 36
|
||||||
|
|
||||||
|
A special thanks to:
|
||||||
|
|
||||||
|
archivas.com and Alan Pinstein, for paying me to focus on their requests
|
||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o removed maximum user+password+hostname size limit
|
o added ability to "upload" to file:// URLs
|
||||||
o removed maximum dir depth limit for FTP
|
o added curl_global_init_mem()
|
||||||
o the ares build now requires c-ares 1.2.0 or later
|
o removed curl_formparse()
|
||||||
o --tcp-nodelay and CURLOPT_TCP_NODELAY were added
|
o the MSVC project file in the release archive is automatically built
|
||||||
o curl/curlver.h contains the libcurl version info now
|
o curl --proxy-digest is a new command line option
|
||||||
|
o the Windows version of libcurl can use wldap32.dll for LDAP
|
||||||
|
o added curl_easy_strerror(), curl_multi_strerror() and curl_share_strerror()
|
||||||
|
o IPv6-enabled Windows hosts now resolves names threaded/asynch as well
|
||||||
|
o configure --with-libidn can be used to point out the root dir of a libidn
|
||||||
|
installation (version 0.4.5 or later) for curl to use, then libcurl can
|
||||||
|
resolve and use IDNA names (domain names with "international" letters)
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o configure --disable-manual works better
|
o incoming cookies with domains set with a prefixed dot now works better
|
||||||
o removed a memory leak when doing a windows threaded resolve and it failed
|
o CURLOPT_COOKIEFILE and CURLOPT_COOKIE can be used in the same request
|
||||||
o --proxy-ntlm now checks if libcurl supports NTLM before using it
|
o improved peer certificate name verification
|
||||||
o minor --fail with authentication bugfix
|
o allocation failures cause no leaks nor crashes
|
||||||
o CURLOPT_IPRESOLVE set to CURL_IPRESOLVE_V6 will now cause a returned error
|
o the progress meter display now handles file sizes up to full 8 exabytes
|
||||||
if the host only can resolve ipv4 addresses
|
(which is as high a signed 64 bit number can reach)
|
||||||
o curl -4/-6 now actually sets the requested option in libcurl
|
o general HTTP authentication improvements
|
||||||
o multi interface on Windows without ares works again
|
o HTTP Digest authentication with the proxy works
|
||||||
o improved resolution for the CURLINFO_*_TIME info variables
|
o mulipart formposting with -F and file names with spaces work again
|
||||||
o getting only a 100 Continue response and nothing else, when talking HTTP,
|
o curl_easy_duphandle() now works when ares-enabled
|
||||||
is now treated as an error by libcurl
|
o HTTP Digest authentication works a lot more like the RFC says
|
||||||
o fixed minor memory leak in libcurl for Windows when statically linked
|
o curl works with telnet and stdin properly on Windows
|
||||||
o POST/PUT using Digest/NTLM/Negotiate (including anyauth) now work better
|
o configure --without-ssl works even when pkg-config has OpenSSL details
|
||||||
o --limit-rate with high speed rates is a lot more accurate now, and supports
|
o src/hugehelp.c builds correct again in non-configure build environments
|
||||||
limiting to speeds >2GB/sec on systems with Large File support.
|
|
||||||
o curl_strnqual.3 "refer-to" man page fix
|
|
||||||
o fixed a minor very old progress meter final update bug
|
|
||||||
o added checks for a working NI_WITHSCOPEID before that is used
|
|
||||||
o fixed a flaw that prevented ares name resolve timeouts to occur
|
|
||||||
o getting user name from http_proxy env variable works now
|
|
||||||
o fixed too early name resolve timeouts with ares
|
|
||||||
o HTTP Digest "re-negotiation" works now
|
|
||||||
o CURLOPT_FAILONERROR (-f/--fail) works with all kinds of authentication
|
|
||||||
o better thread-safety thanks to the internal strerror() replacement
|
|
||||||
o better thread-safety on AIX thanks to better function detection
|
|
||||||
o minor ipv6 build fix for windows
|
|
||||||
o the test suite runs fine with mingw-built curl
|
|
||||||
o the postit2.c example works now
|
|
||||||
o better error message when --interface fails on windows
|
|
||||||
o the progress meter now displays very long times better
|
|
||||||
o CURLINFO_CONTENT_LENGTH_DOWNLOAD with CURLOPT_NOBODY set TRUE now works
|
|
||||||
o passwords longer than 14 letters work with NTLM
|
|
||||||
o 'make netware' in the root dir works now
|
|
||||||
o builds fine on VMS again and even nicer than before
|
|
||||||
|
|
||||||
Other curl-related news since the previous public release:
|
Other curl-related news since the previous public release:
|
||||||
|
|
||||||
o PycURL 7.11.1 was released: http://pycurl.sf.net/
|
o The CVS repository was moved to cool.haxx.se
|
||||||
o CURLHandle 1.9 was released: http://curlhandle.sourceforge.net/
|
o AdacURL 7.11.2 was released: http://www.almroth.com/adacurl/
|
||||||
o A curl module for the Q language was announced:
|
o PycURL 7.11.3 was released: http://pycurl.sourceforge.net
|
||||||
http://q-lang.sourceforge.net/
|
o A new German download mirror: http://www.mirrorspace.org/curl/
|
||||||
o c-ares 1.2.0 was released: http://daniel.haxx.se/projects/c-ares/
|
o Two new mailing lists are available:
|
||||||
o New curl web mirrors:
|
curl-and-python - for python programmers using pycurl or curl
|
||||||
Germany http://curl.netmirror.org/
|
curl-perl-commmits - receives commits done to the curl-perl CVS module
|
||||||
USA http://curl.signal42.com/
|
|
||||||
Denmark http://curl.cofman.dk/
|
|
||||||
|
|
||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Thomas Schwinge, Marty Kuhrt, G<>nter Knauf, Kevin Roth, Glen Nakamura, Gisle
|
Gisle Vanem, Tommy Tam, Luca Altea, James Bursa, Mihai Ionescu, Michael
|
||||||
Vanem, Greg Hewgill, Joe Halpin, Tor Arntsen, Dirk Manske, Roy Shan, Mitz
|
Benedict, Andr<64>s Garc<72>a, Joe Halpin, Seshubabu Pasam, Peter Sylvester, Robert
|
||||||
Wark, Andr<64>s Garc<72>a, Robin Kay, Alan Pinstein, David Byron, Nathan
|
D. Young, Jesse Noller, David Byron, Massimiliano Ziccardi, Mohun Biswas,
|
||||||
O'Sullivan, Erwin Authried
|
Renaud Duhaut
|
||||||
|
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
|||||||
30
TODO-RELEASE
30
TODO-RELEASE
@@ -3,35 +3,11 @@ Issues not sorted in any particular order.
|
|||||||
UNASSIGNED means that no person has publicly stated to work on the issue.
|
UNASSIGNED means that no person has publicly stated to work on the issue.
|
||||||
DELETE means the issue is subject for dismissal
|
DELETE means the issue is subject for dismissal
|
||||||
|
|
||||||
To get fixed in 7.11.2 (planned release late April 2004)
|
To get fixed in 7.12.0 (planned release: June 2004)
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
To get fixed in 7.12.1 (planned release: August 2004)
|
||||||
To get fixed in 7.12.0 (no date)
|
|
||||||
======================
|
======================
|
||||||
|
|
||||||
25. curl_easy_strerror() curl_multi_strerror() curl_share_strerror()
|
* FTP 3rd party transfers
|
||||||
Code already in CVS. Messages need overview/improvements.
|
|
||||||
Medium prio.
|
|
||||||
|
|
||||||
26. i18n of error messages?
|
|
||||||
Low prio. Nobody has volunteered. Subject for removal.
|
|
||||||
|
|
||||||
33. Add a function to replace the malloc-calls within libcurl.
|
|
||||||
Low prio. Seshubabu Pasam works on this.
|
|
||||||
|
|
||||||
35. Rearrange lib/hostip.c to reduce the amount of #ifdefs and make it easier
|
|
||||||
to understand and edit. Daniel works on this. See
|
|
||||||
http://curl.haxx.se/beta/hostip-cleanup1.patch
|
|
||||||
Medium prio.
|
|
||||||
|
|
||||||
36. Add support for a threaded getaddrinfo() on Windows and IPv6 enabled
|
|
||||||
libcurl.
|
|
||||||
|
|
||||||
37. Configure option "--with-libidn" to support IDNA (Internationalising
|
|
||||||
Domain Names in Applications). Translate to/from ACE encoded domain
|
|
||||||
names as needed.
|
|
||||||
|
|
||||||
38. Make the ldap protocol work with Windows' built-in LDAP-client.
|
|
||||||
I.e. dynamically link to WLDAP32.DLL and add ldap URL parsing
|
|
||||||
(WLDAP32.DLL doesn't have an UTF-8 ldap_url_parse).
|
|
||||||
|
|||||||
19
acinclude.m4
19
acinclude.m4
@@ -396,6 +396,17 @@ AC_DEFUN([CURL_CHECK_STRERROR_R],
|
|||||||
AC_MSG_RESULT(no))])])
|
AC_MSG_RESULT(no))])])
|
||||||
|
|
||||||
if test "x$strerror_r" = "xyes"; then
|
if test "x$strerror_r" = "xyes"; then
|
||||||
|
|
||||||
|
dnl check if strerror_r is properly declared in the headers
|
||||||
|
AC_CHECK_DECL(strerror_r, ,
|
||||||
|
AC_DEFINE(HAVE_NO_STRERROR_R_DECL, 1, [we have no strerror_r() proto])
|
||||||
|
,
|
||||||
|
[#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
])
|
||||||
|
|
||||||
dnl determine if this strerror_r() is glibc or POSIX
|
dnl determine if this strerror_r() is glibc or POSIX
|
||||||
AC_MSG_CHECKING([for a glibc strerror_r API])
|
AC_MSG_CHECKING([for a glibc strerror_r API])
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
@@ -658,10 +669,11 @@ AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
|||||||
dnl "invalid format string conversion"
|
dnl "invalid format string conversion"
|
||||||
dnl * 279 warns on static conditions in while expressions
|
dnl * 279 warns on static conditions in while expressions
|
||||||
dnl * 981 warns on "operands are evaluated in unspecified order"
|
dnl * 981 warns on "operands are evaluated in unspecified order"
|
||||||
|
dnl * 1418 "external definition with no prior declaration"
|
||||||
dnl * 1419 warns on "external declaration in primary source file"
|
dnl * 1419 warns on "external declaration in primary source file"
|
||||||
dnl which we know and do on purpose.
|
dnl which we know and do on purpose.
|
||||||
|
|
||||||
WARN="-wd279,269,1419,981"
|
WARN="-wd279,269,981,1418,1419"
|
||||||
|
|
||||||
if test "$gccnum" -gt "600"; then
|
if test "$gccnum" -gt "600"; then
|
||||||
dnl icc 6.0 and older doesn't have the -Wall flag
|
dnl icc 6.0 and older doesn't have the -Wall flag
|
||||||
@@ -697,6 +709,11 @@ AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
|||||||
WARN="$WARN -Wendif-labels -Wstrict-prototypes"
|
WARN="$WARN -Wendif-labels -Wstrict-prototypes"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$gccnum" -ge "304"; then
|
||||||
|
# try -Wunreachable-code on gcc 3.4
|
||||||
|
WARN="$WARN -Wunreachable-code"
|
||||||
|
fi
|
||||||
|
|
||||||
for flag in $CPPFLAGS; do
|
for flag in $CPPFLAGS; do
|
||||||
case "$flag" in
|
case "$flag" in
|
||||||
-I*)
|
-I*)
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
Changelog for the c-ares project
|
Changelog for the c-ares project
|
||||||
|
|
||||||
|
* May 11
|
||||||
|
- Nico Stappenbelt reported that when processing domain and search lines in
|
||||||
|
the resolv.conf file, the first entry encountered is processed and used as
|
||||||
|
the search list. According to the manual pages for both Linux, Solaris and
|
||||||
|
Tru64, the last entry of either a domain or a search field is used.
|
||||||
|
|
||||||
|
This is now adjusted in the code
|
||||||
|
|
||||||
Version 1.2.0 (April 13, 2004)
|
Version 1.2.0 (April 13, 2004)
|
||||||
|
|
||||||
* April 2, 2004
|
* April 2, 2004
|
||||||
|
|||||||
@@ -143,25 +143,29 @@ int ares__get_hostent(FILE *fp, struct hostent **host)
|
|||||||
free(line);
|
free(line);
|
||||||
return ARES_SUCCESS;
|
return ARES_SUCCESS;
|
||||||
}
|
}
|
||||||
free(line);
|
if(line)
|
||||||
|
free(line);
|
||||||
|
|
||||||
if (status == ARES_SUCCESS)
|
if (status == ARES_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Memory allocation failure; clean up. */
|
/* Memory allocation failure; clean up. */
|
||||||
if (hostent)
|
if (hostent)
|
||||||
{
|
{
|
||||||
free((char *) hostent->h_name);
|
if(hostent->h_name)
|
||||||
|
free((char *) hostent->h_name);
|
||||||
if (hostent->h_aliases)
|
if (hostent->h_aliases)
|
||||||
{
|
{
|
||||||
for (alias = hostent->h_aliases; *alias; alias++)
|
for (alias = hostent->h_aliases; *alias; alias++)
|
||||||
free(*alias);
|
free(*alias);
|
||||||
}
|
}
|
||||||
free(hostent->h_aliases);
|
if(hostent->h_aliases)
|
||||||
if (hostent->h_addr_list)
|
free(hostent->h_aliases);
|
||||||
|
if (hostent->h_addr_list && hostent->h_addr_list[0])
|
||||||
free(hostent->h_addr_list[0]);
|
free(hostent->h_addr_list[0]);
|
||||||
free(hostent->h_addr_list);
|
if(hostent->h_addr_list)
|
||||||
|
free(hostent->h_addr_list);
|
||||||
|
free(hostent);
|
||||||
}
|
}
|
||||||
free(hostent);
|
|
||||||
return ARES_ENOMEM;
|
return ARES_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
|||||||
channel->nsort = -1;
|
channel->nsort = -1;
|
||||||
channel->lookups = NULL;
|
channel->lookups = NULL;
|
||||||
channel->queries = NULL;
|
channel->queries = NULL;
|
||||||
|
channel->domains = NULL;
|
||||||
|
channel->sortlist = NULL;
|
||||||
|
|
||||||
/* Initialize configuration by each of the four sources, from highest
|
/* Initialize configuration by each of the four sources, from highest
|
||||||
* precedence to lowest.
|
* precedence to lowest.
|
||||||
@@ -101,15 +103,16 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
|||||||
/* Something failed; clean up memory we may have allocated. */
|
/* Something failed; clean up memory we may have allocated. */
|
||||||
if (channel->nservers != -1)
|
if (channel->nservers != -1)
|
||||||
free(channel->servers);
|
free(channel->servers);
|
||||||
if (channel->ndomains != -1)
|
if (channel->domains)
|
||||||
{
|
{
|
||||||
for (i = 0; i < channel->ndomains; i++)
|
for (i = 0; i < channel->ndomains; i++)
|
||||||
free(channel->domains[i]);
|
free(channel->domains[i]);
|
||||||
free(channel->domains);
|
free(channel->domains);
|
||||||
}
|
}
|
||||||
if (channel->nsort != -1)
|
if (channel->sortlist)
|
||||||
free(channel->sortlist);
|
free(channel->sortlist);
|
||||||
free(channel->lookups);
|
if(channel->lookups)
|
||||||
|
free(channel->lookups);
|
||||||
free(channel);
|
free(channel);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -436,11 +439,11 @@ DhcpNameServer
|
|||||||
return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
|
return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
|
||||||
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
|
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
|
||||||
{
|
{
|
||||||
if ((p = try_config(line, "domain")) && channel->ndomains == -1)
|
if ((p = try_config(line, "domain")))
|
||||||
status = config_domain(channel, p);
|
status = config_domain(channel, p);
|
||||||
else if ((p = try_config(line, "lookup")) && !channel->lookups)
|
else if ((p = try_config(line, "lookup")) && !channel->lookups)
|
||||||
status = config_lookup(channel, p);
|
status = config_lookup(channel, p);
|
||||||
else if ((p = try_config(line, "search")) && channel->ndomains == -1)
|
else if ((p = try_config(line, "search")))
|
||||||
status = set_search(channel, p);
|
status = set_search(channel, p);
|
||||||
else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
|
else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
|
||||||
status = config_nameserver(&servers, &nservers, p);
|
status = config_nameserver(&servers, &nservers, p);
|
||||||
@@ -453,7 +456,8 @@ DhcpNameServer
|
|||||||
if (status != ARES_SUCCESS)
|
if (status != ARES_SUCCESS)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(line);
|
if(line)
|
||||||
|
free(line);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,8 +466,10 @@ DhcpNameServer
|
|||||||
/* Handle errors. */
|
/* Handle errors. */
|
||||||
if (status != ARES_EOF)
|
if (status != ARES_EOF)
|
||||||
{
|
{
|
||||||
if (servers != NULL) free(servers);
|
if (servers != NULL)
|
||||||
if (sortlist != NULL) free(sortlist);
|
free(servers);
|
||||||
|
if (sortlist != NULL)
|
||||||
|
free(sortlist);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,6 +707,14 @@ static int set_search(ares_channel channel, const char *str)
|
|||||||
int n;
|
int n;
|
||||||
const char *p, *q;
|
const char *p, *q;
|
||||||
|
|
||||||
|
if(channel->ndomains != -1) {
|
||||||
|
/* if we already have some domains present, free them first */
|
||||||
|
for(n=0; n < channel->ndomains; n++)
|
||||||
|
free(channel->domains[n]);
|
||||||
|
free(channel->domains);
|
||||||
|
channel->ndomains = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Count the domains given. */
|
/* Count the domains given. */
|
||||||
n = 0;
|
n = 0;
|
||||||
p = str;
|
p = str;
|
||||||
|
|||||||
@@ -124,7 +124,12 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
|
|||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* failed, free the malloc()ed memory */
|
||||||
|
free(squery->name);
|
||||||
|
free(squery);
|
||||||
callback(arg, status, NULL, 0);
|
callback(arg, status, NULL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
buildconf
14
buildconf
@@ -157,27 +157,27 @@ fi
|
|||||||
# run the correct scripts now
|
# run the correct scripts now
|
||||||
|
|
||||||
echo "buildconf: running libtoolize"
|
echo "buildconf: running libtoolize"
|
||||||
${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The command '${LIBTOOLIZE:-libtoolize} --copy --automake --force' failed"
|
${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The libtool command failed"
|
||||||
echo "buildconf: running aclocal"
|
echo "buildconf: running aclocal"
|
||||||
${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The command '${ACLOCAL:-aclocal}${ACLOCAL_FLAGS:+" $ACLOCAL_FLAGS"}' failed"
|
${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The aclocal command line failed"
|
||||||
echo "buildconf: running aclocal hack to convert all mv to mv -f"
|
echo "buildconf: running aclocal hack to convert all mv to mv -f"
|
||||||
perl -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
|
perl -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
|
||||||
echo "buildconf: running autoheader"
|
echo "buildconf: running autoheader"
|
||||||
${AUTOHEADER:-autoheader} || die "The command '${AUTOHEADER:-autoheader}' failed"
|
${AUTOHEADER:-autoheader} || die "The autoheader command failed"
|
||||||
echo "buildconf: running autoconf"
|
echo "buildconf: running autoconf"
|
||||||
${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed"
|
${AUTOCONF:-autoconf} || die "The autoconf command failed"
|
||||||
|
|
||||||
if test -d ares; then
|
if test -d ares; then
|
||||||
cd ares
|
cd ares
|
||||||
echo "buildconf: running aclocal in the ares directory"
|
echo "buildconf: running aclocal in the ares directory"
|
||||||
${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The command '${ACLOCAL:-aclocal}${ACLOCAL_FLAGS:+" $ACLOCAL_FLAGS"}' failed"
|
${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The ares aclocal command failed"
|
||||||
echo "buildconf: running autoconf in the ares directory"
|
echo "buildconf: running autoconf in the ares directory"
|
||||||
${AUTOCONF:-autoconf} || die "The command '${AUTOCONF:-autoconf}' failed"
|
${AUTOCONF:-autoconf} || die "The ares autoconf command failed"
|
||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "buildconf: running automake"
|
echo "buildconf: running automake"
|
||||||
${AUTOMAKE:-automake} -a || die "The command '${AUTOMAKE:-automake} -a' failed"
|
${AUTOMAKE:-automake} -a || die "The automake command failed"
|
||||||
|
|
||||||
echo "buildconf: OK"
|
echo "buildconf: OK"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
220
configure.ac
220
configure.ac
@@ -16,12 +16,24 @@ AM_CONFIG_HEADER(lib/config.h src/config.h)
|
|||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
dnl SED is needed by some of the tools
|
dnl SED is needed by some of the tools
|
||||||
AC_PATH_PROG( SED, sed, , $PATH:/usr/bin:/usr/local/bin)
|
AC_PATH_PROG( SED, sed, sed-was-not-found-by-configure,
|
||||||
|
$PATH:/usr/bin:/usr/local/bin)
|
||||||
AC_SUBST(SED)
|
AC_SUBST(SED)
|
||||||
|
|
||||||
|
if test "x$SED" = "xsed-was-not-found-by-configure"; then
|
||||||
|
AC_MSG_WARN([sed was not found, this may ruin your chances to build fine])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl AR is used by libtool, and try the odd Solaris path too
|
dnl AR is used by libtool, and try the odd Solaris path too
|
||||||
AC_PATH_PROG( AR, ar, , $PATH:/usr/bin:/usr/local/bin:/usr/ccs/bin)
|
dnl we use AC_CHECK_TOOL since this should make a library for the target
|
||||||
|
dnl platform
|
||||||
|
AC_CHECK_TOOL(AR, ar,
|
||||||
|
ar-was-not-found-by-configure,
|
||||||
|
$PATH:/usr/bin:/usr/local/bin:/usr/ccs/bin)
|
||||||
AC_SUBST(AR)
|
AC_SUBST(AR)
|
||||||
|
if test "x$AR" = "xar-was-not-found-by-configure"; then
|
||||||
|
AC_MSG_WARN([ar was not found, this may ruin your chances to build fine])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl figure out the libcurl version
|
dnl figure out the libcurl version
|
||||||
VERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h`
|
VERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curlver.h`
|
||||||
@@ -42,6 +54,17 @@ AC_SUBST(PKGADD_PKG)
|
|||||||
AC_SUBST(PKGADD_NAME)
|
AC_SUBST(PKGADD_NAME)
|
||||||
AC_SUBST(PKGADD_VENDOR)
|
AC_SUBST(PKGADD_VENDOR)
|
||||||
|
|
||||||
|
dnl
|
||||||
|
dnl initialize all the info variables to 'no'
|
||||||
|
curl_ssl_msg="no (--with-ssl)"
|
||||||
|
curl_zlib_msg="no (--with-zlib)"
|
||||||
|
curl_krb4_msg="no (--with-krb4*)"
|
||||||
|
curl_gss_msg="no (--with-gssapi)"
|
||||||
|
curl_spnego_msg="no (--with-spnego)"
|
||||||
|
curl_ares_msg="no (--enable-ares)"
|
||||||
|
curl_ipv6_msg="no (--enable-ipv6)"
|
||||||
|
curl_idn_msg="no (--with-libidn)"
|
||||||
|
curl_manual_msg="no (--enable-manual)"
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl Detect the canonical host and target build environment
|
dnl Detect the canonical host and target build environment
|
||||||
@@ -258,7 +281,7 @@ dnl At least one system has been identified to require BOTH nsl and socket
|
|||||||
dnl libs at the same time to link properly.
|
dnl libs at the same time to link properly.
|
||||||
if test "$HAVE_GETHOSTBYNAME" != "1"
|
if test "$HAVE_GETHOSTBYNAME" != "1"
|
||||||
then
|
then
|
||||||
AC_MSG_CHECKING([trying gethostbyname with both nsl and socket libs])
|
AC_MSG_CHECKING([for gethostbyname with both nsl and socket libs])
|
||||||
my_ac_save_LIBS=$LIBS
|
my_ac_save_LIBS=$LIBS
|
||||||
LIBS="-lnsl -lsocket $LIBS"
|
LIBS="-lnsl -lsocket $LIBS"
|
||||||
AC_TRY_LINK( ,
|
AC_TRY_LINK( ,
|
||||||
@@ -383,6 +406,8 @@ main()
|
|||||||
))
|
))
|
||||||
|
|
||||||
if test "$ipv6" = "yes"; then
|
if test "$ipv6" = "yes"; then
|
||||||
|
curl_ipv6_msg="enabled"
|
||||||
|
|
||||||
CURL_CHECK_WORKING_GETADDRINFO
|
CURL_CHECK_WORKING_GETADDRINFO
|
||||||
|
|
||||||
CURL_CHECK_NI_WITHSCOPEID
|
CURL_CHECK_NI_WITHSCOPEID
|
||||||
@@ -549,6 +574,8 @@ then
|
|||||||
KRB4_ENABLED=1
|
KRB4_ENABLED=1
|
||||||
AC_SUBST(KRB4_ENABLED)
|
AC_SUBST(KRB4_ENABLED)
|
||||||
|
|
||||||
|
curl_krb4_msg="enabled"
|
||||||
|
|
||||||
dnl the krb4 stuff needs a strlcpy()
|
dnl the krb4 stuff needs a strlcpy()
|
||||||
AC_CHECK_FUNCS(strlcpy)
|
AC_CHECK_FUNCS(strlcpy)
|
||||||
|
|
||||||
@@ -582,7 +609,9 @@ if test x"$want_spnego" = xyes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_SPNEGO, 1, [Define this if you have the SPNEGO library fbopenssl])
|
AC_DEFINE(HAVE_SPNEGO, 1,
|
||||||
|
[Define this if you have the SPNEGO library fbopenssl])
|
||||||
|
curl_spnego_msg="enabled"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
@@ -638,6 +667,8 @@ if test x"$want_gss" = xyes; then
|
|||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GSSAPI, 1, [if you have the gssapi libraries])
|
AC_DEFINE(HAVE_GSSAPI, 1, [if you have the gssapi libraries])
|
||||||
|
|
||||||
|
curl_gss_msg="enabled"
|
||||||
|
|
||||||
if test -n "$GSSAPI_INCS"; then
|
if test -n "$GSSAPI_INCS"; then
|
||||||
# cut off the preceding -I from the include path
|
# cut off the preceding -I from the include path
|
||||||
GSSAPI_INCS=`echo $GSSAPI_INCS | sed -e s/^-I//g`
|
GSSAPI_INCS=`echo $GSSAPI_INCS | sed -e s/^-I//g`
|
||||||
@@ -653,33 +684,6 @@ else
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
dnl Detect the pkg-config tool, as it may have extra info about the
|
|
||||||
dnl openssl installation we can use. I *believe* this is what we are
|
|
||||||
dnl expected to do on really recent Redhat Linux hosts.
|
|
||||||
AC_PATH_PROG( PKGCONFIG, pkg-config, no, $PATH:/usr/bin:/usr/local/bin)
|
|
||||||
if test "$PKGCONFIG" != "no" ; then
|
|
||||||
AC_MSG_CHECKING([for OpenSSL options using pkg-config])
|
|
||||||
|
|
||||||
$PKGCONFIG --exists openssl
|
|
||||||
SSL_EXISTS=$?
|
|
||||||
|
|
||||||
if test "$SSL_EXISTS" -eq "0"; then
|
|
||||||
SSL_LIBS=`$PKGCONFIG --libs-only-l openssl 2>/dev/null`
|
|
||||||
SSL_LDFLAGS=`$PKGCONFIG --libs-only-L openssl 2>/dev/null`
|
|
||||||
SSL_CPPFLAGS=`$PKGCONFIG --cflags-only-I openssl 2>/dev/null`
|
|
||||||
|
|
||||||
LIBS="$LIBS $SSL_LIBS"
|
|
||||||
CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS"
|
|
||||||
LDFLAGS="$LDFLAGS $SSL_LDFLAGS"
|
|
||||||
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
dnl Check for the presence of SSL libraries and headers
|
dnl Check for the presence of SSL libraries and headers
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
@@ -698,11 +702,36 @@ then
|
|||||||
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more])
|
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more])
|
||||||
else
|
else
|
||||||
|
|
||||||
dnl Check for and handle argument to --with-ssl.
|
dnl backup the pre-ssl variables
|
||||||
|
|
||||||
dnl save the pre-ssl check flags for a while
|
|
||||||
CLEANLDFLAGS="$LDFLAGS"
|
CLEANLDFLAGS="$LDFLAGS"
|
||||||
CLEANCPPFLAGS="$CPPFLAGS"
|
CLEANCPPFLAGS="$CPPFLAGS"
|
||||||
|
CLEANLIBS="$LIBS"
|
||||||
|
|
||||||
|
dnl Detect the pkg-config tool, as it may have extra info about the openssl
|
||||||
|
dnl installation we can use. I *believe* this is what we are expected to do
|
||||||
|
dnl on really recent Redhat Linux hosts.
|
||||||
|
|
||||||
|
AC_PATH_PROG( PKGCONFIG, pkg-config, no, $PATH:/usr/bin:/usr/local/bin)
|
||||||
|
if test "$PKGCONFIG" != "no" ; then
|
||||||
|
AC_MSG_CHECKING([OpenSSL options with pkg-config])
|
||||||
|
|
||||||
|
$PKGCONFIG --exists openssl
|
||||||
|
SSL_EXISTS=$?
|
||||||
|
|
||||||
|
if test "$SSL_EXISTS" -eq "0"; then
|
||||||
|
SSL_LIBS=`$PKGCONFIG --libs-only-l openssl 2>/dev/null`
|
||||||
|
SSL_LDFLAGS=`$PKGCONFIG --libs-only-L openssl 2>/dev/null`
|
||||||
|
SSL_CPPFLAGS=`$PKGCONFIG --cflags-only-I openssl 2>/dev/null`
|
||||||
|
|
||||||
|
dnl use the values pkg-config reported
|
||||||
|
LIBS="$LIBS $SSL_LIBS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS"
|
||||||
|
LDFLAGS="$LDFLAGS $SSL_LDFLAGS"
|
||||||
|
AC_MSG_RESULT([found])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
case "$OPT_SSL" in
|
case "$OPT_SSL" in
|
||||||
yes)
|
yes)
|
||||||
@@ -720,14 +749,13 @@ else
|
|||||||
AC_CHECK_LIB(crypto, CRYPTO_lock,[
|
AC_CHECK_LIB(crypto, CRYPTO_lock,[
|
||||||
HAVECRYPTO="yes"
|
HAVECRYPTO="yes"
|
||||||
],[
|
],[
|
||||||
OLDLDFLAGS="$LDFLAGS"
|
|
||||||
OLDCPPFLAGS="$CPPFLAGS"
|
|
||||||
LDFLAGS="$CLEANLDFLAGS -L$EXTRA_SSL/lib$libsuff"
|
LDFLAGS="$CLEANLDFLAGS -L$EXTRA_SSL/lib$libsuff"
|
||||||
CPPFLAGS="$CLEANCPPFLAGS -I$EXTRA_SSL/include/openssl -I$EXTRA_SSL/include"
|
CPPFLAGS="$CLEANCPPFLAGS -I$EXTRA_SSL/include/openssl -I$EXTRA_SSL/include"
|
||||||
AC_CHECK_LIB(crypto, CRYPTO_add_lock,[
|
AC_CHECK_LIB(crypto, CRYPTO_add_lock,[
|
||||||
HAVECRYPTO="yes" ], [
|
HAVECRYPTO="yes" ], [
|
||||||
LDFLAGS="$OLDLDFLAGS"
|
LDFLAGS="$CLEANLDFLAGS"
|
||||||
CPPFLAGS="$OLDCPPFLAGS"
|
CPPFLAGS="$CLEANCPPFLAGS"
|
||||||
|
LIBS="$CLEANLIBS"
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -772,10 +800,12 @@ else
|
|||||||
dnl Check for SSLeay headers
|
dnl Check for SSLeay headers
|
||||||
AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
|
AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
|
||||||
openssl/pem.h openssl/ssl.h openssl/err.h,
|
openssl/pem.h openssl/ssl.h openssl/err.h,
|
||||||
|
curl_ssl_msg="enabled"
|
||||||
OPENSSL_ENABLED=1)
|
OPENSSL_ENABLED=1)
|
||||||
|
|
||||||
if test $ac_cv_header_openssl_x509_h = no; then
|
if test $ac_cv_header_openssl_x509_h = no; then
|
||||||
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h,
|
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h,
|
||||||
|
curl_ssl_msg="enabled"
|
||||||
OPENSSL_ENABLED=1)
|
OPENSSL_ENABLED=1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -896,6 +926,7 @@ case "$OPT_ZLIB" in
|
|||||||
dnl replace 'HAVE_LIBZ' in the automake makefile.ams
|
dnl replace 'HAVE_LIBZ' in the automake makefile.ams
|
||||||
AMFIXLIB="1"
|
AMFIXLIB="1"
|
||||||
AC_MSG_NOTICE([found both libz and libz.h header])
|
AC_MSG_NOTICE([found both libz and libz.h header])
|
||||||
|
curl_zlib_msg="enabled"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -903,6 +934,43 @@ esac
|
|||||||
dnl set variable for use in automakefile(s)
|
dnl set variable for use in automakefile(s)
|
||||||
AM_CONDITIONAL(HAVE_LIBZ, test x"$AMFIXLIB" = x1)
|
AM_CONDITIONAL(HAVE_LIBZ, test x"$AMFIXLIB" = x1)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to build with libidn])
|
||||||
|
AC_ARG_WITH(libidn,
|
||||||
|
AC_HELP_STRING([--with-libidn=PATH],[Enable libidn usage])
|
||||||
|
AC_HELP_STRING([--without-libidn],[Disable libidn usage]),
|
||||||
|
[LIBIDN="$withval"])
|
||||||
|
|
||||||
|
case "$LIBIDN" in
|
||||||
|
no)
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
;;
|
||||||
|
*) AC_MSG_RESULT(yes)
|
||||||
|
AC_CHECK_LIB(idn, idna_to_ascii_lz, ,
|
||||||
|
[
|
||||||
|
dnl if there was a given path, try it
|
||||||
|
nolibidn="true"
|
||||||
|
if test "x$LIBIDN" != "xyes"; then
|
||||||
|
nolibidn="" dnl reset to test again
|
||||||
|
oldLDFLAGS=$LDFLAGS
|
||||||
|
oldCPPFLAGS=$CPPFLAGS
|
||||||
|
LDFLAGS="$LDFLAGS -L$LIBIDN/lib"
|
||||||
|
CPPFLAGS="$CPPFLAGS -I$LIBIDN/include"
|
||||||
|
AC_CHECK_LIB(idn, idna_to_ascii_4i, ,
|
||||||
|
nolibidn="true"
|
||||||
|
LDFLAGS=$oldLDFLAGS
|
||||||
|
CPPFLAGS=$oldCPPFLAGS)
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
if test "x$nolibidn" != "xtrue"; then
|
||||||
|
curl_idn_msg="enabled"
|
||||||
|
dnl different versions of libidn have different setups of these:
|
||||||
|
AC_CHECK_FUNCS( idn_free )
|
||||||
|
AC_CHECK_HEADERS( idn-free.h )
|
||||||
|
fi
|
||||||
|
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
dnl Default is to try the thread-safe versions of a few functions
|
dnl Default is to try the thread-safe versions of a few functions
|
||||||
OPT_THREAD=on
|
OPT_THREAD=on
|
||||||
|
|
||||||
@@ -1055,6 +1123,7 @@ AC_CHECK_SIZEOF(curl_off_t, ,[
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "$srcdir/include/curl/curl.h"
|
#include "$srcdir/include/curl/curl.h"
|
||||||
])
|
])
|
||||||
|
AC_CHECK_SIZEOF(size_t)
|
||||||
|
|
||||||
AC_CHECK_TYPE(long long,
|
AC_CHECK_TYPE(long long,
|
||||||
[AC_DEFINE(HAVE_LONGLONG, 1, [if your compiler supports 'long long'])])
|
[AC_DEFINE(HAVE_LONGLONG, 1, [if your compiler supports 'long long'])])
|
||||||
@@ -1192,41 +1261,12 @@ dnl manual
|
|||||||
|
|
||||||
if test "$USE_MANUAL" = "1"; then
|
if test "$USE_MANUAL" = "1"; then
|
||||||
AC_DEFINE(USE_MANUAL, 1, [If you want to build curl with the built-in manual])
|
AC_DEFINE(USE_MANUAL, 1, [If you want to build curl with the built-in manual])
|
||||||
|
curl_manual_msg="enabled"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl set variable for use in automakefile(s)
|
dnl set variable for use in automakefile(s)
|
||||||
AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1)
|
AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1)
|
||||||
|
|
||||||
|
|
||||||
dnl AC_PATH_PROG( RANLIB, ranlib, /usr/bin/ranlib,
|
|
||||||
dnl $PATH:/usr/bin/:/usr/local/bin )
|
|
||||||
dnl AC_SUBST(RANLIB)
|
|
||||||
|
|
||||||
dnl ************************************************************
|
|
||||||
dnl lame option to switch on debug options
|
|
||||||
dnl
|
|
||||||
AC_MSG_CHECKING([whether to enable debug options])
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
AC_HELP_STRING([--enable-debug],[Enable pedantic debug options])
|
|
||||||
AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
|
||||||
[ case "$enableval" in
|
|
||||||
no)
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
;;
|
|
||||||
*) AC_MSG_RESULT(yes)
|
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DCURLDEBUG"
|
|
||||||
CFLAGS="$CFLAGS -g"
|
|
||||||
|
|
||||||
dnl set compiler "debug" options to become more picky, and remove
|
|
||||||
dnl optimize options from CFLAGS
|
|
||||||
CURL_CC_DEBUG_OPTS
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
],
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether to enable ares])
|
AC_MSG_CHECKING([whether to enable ares])
|
||||||
AC_ARG_ENABLE(ares,
|
AC_ARG_ENABLE(ares,
|
||||||
AC_HELP_STRING([--enable-ares=PATH],[Enable ares for name lookups])
|
AC_HELP_STRING([--enable-ares=PATH],[Enable ares for name lookups])
|
||||||
@@ -1245,6 +1285,7 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
|
|||||||
dnl substitute HAVE_ARES for curl-config and similar
|
dnl substitute HAVE_ARES for curl-config and similar
|
||||||
HAVE_ARES="1"
|
HAVE_ARES="1"
|
||||||
AC_SUBST(HAVE_ARES)
|
AC_SUBST(HAVE_ARES)
|
||||||
|
curl_ares_msg="enabled"
|
||||||
|
|
||||||
LIBS="$LIBS -lcares"
|
LIBS="$LIBS -lcares"
|
||||||
|
|
||||||
@@ -1299,6 +1340,31 @@ int main(void)
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl ************************************************************
|
||||||
|
dnl lame option to switch on debug options
|
||||||
|
dnl
|
||||||
|
AC_MSG_CHECKING([whether to enable debug options])
|
||||||
|
AC_ARG_ENABLE(debug,
|
||||||
|
AC_HELP_STRING([--enable-debug],[Enable pedantic debug options])
|
||||||
|
AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||||
|
[ case "$enableval" in
|
||||||
|
no)
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
;;
|
||||||
|
*) AC_MSG_RESULT(yes)
|
||||||
|
|
||||||
|
CPPFLAGS="$CPPFLAGS -DCURLDEBUG"
|
||||||
|
CFLAGS="$CFLAGS -g"
|
||||||
|
|
||||||
|
dnl set compiler "debug" options to become more picky, and remove
|
||||||
|
dnl optimize options from CFLAGS
|
||||||
|
CURL_CC_DEBUG_OPTS
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
],
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
)
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile \
|
AC_CONFIG_FILES([Makefile \
|
||||||
docs/Makefile \
|
docs/Makefile \
|
||||||
docs/examples/Makefile \
|
docs/examples/Makefile \
|
||||||
@@ -1326,3 +1392,21 @@ AC_CONFIG_FILES([Makefile \
|
|||||||
curl-config
|
curl-config
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||||
|
|
||||||
|
curl version: ${VERSION}
|
||||||
|
Host setup: ${host}
|
||||||
|
Install prefix: ${prefix}
|
||||||
|
Compiler: ${CC}
|
||||||
|
SSL support: ${curl_ssl_msg}
|
||||||
|
zlib support: ${curl_zlib_msg}
|
||||||
|
krb4 support: ${curl_krb4_msg}
|
||||||
|
GSSAPI support: ${curl_gss_msg}
|
||||||
|
SNPEGO support: ${curl_spnego_msg}
|
||||||
|
c-ares support: ${curl_ares_msg}
|
||||||
|
ipv6 support: ${curl_ipv6_msg}
|
||||||
|
IDN support: ${curl_idn_msg}
|
||||||
|
Build libcurl: Shared=${enable_shared}, Static=${enable_static}
|
||||||
|
Built-in manual: ${curl_manual_msg}
|
||||||
|
])
|
||||||
|
|||||||
@@ -33,7 +33,10 @@
|
|||||||
;; keybindings for C, C++, and Objective-C. We can put these in
|
;; keybindings for C, C++, and Objective-C. We can put these in
|
||||||
;; c-mode-base-map because of inheritance ...
|
;; c-mode-base-map because of inheritance ...
|
||||||
(define-key c-mode-base-map "\M-q" 'c-fill-paragraph)
|
(define-key c-mode-base-map "\M-q" 'c-fill-paragraph)
|
||||||
|
(define-key c-mode-base-map "\M-m" 'delete-trailing-whitespace)
|
||||||
(setq c-recognize-knr-p nil)
|
(setq c-recognize-knr-p nil)
|
||||||
|
;;; (add-hook 'write-file-hooks 'delete-trailing-whitespace t)
|
||||||
|
(setq show-trailing-whitespace t)
|
||||||
)
|
)
|
||||||
|
|
||||||
;; Set this is in your .emacs if you want to use the c-mode-hook as
|
;; Set this is in your .emacs if you want to use the c-mode-hook as
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ join in and help us correct one or more of these! Also be sure to check the
|
|||||||
changelog of the current development status, as one or more of these problems
|
changelog of the current development status, as one or more of these problems
|
||||||
may have been fixed since this was written!
|
may have been fixed since this was written!
|
||||||
|
|
||||||
|
* If you use a very large amount of file descriptors (more than FD_SETSIZE)
|
||||||
|
and then use libcurl, it might crash on its use of select() which then
|
||||||
|
stores data out of bounds. Bug report #948950.
|
||||||
|
|
||||||
* --limit-rate using -d or -F does not work. This is because the limit logic
|
* --limit-rate using -d or -F does not work. This is because the limit logic
|
||||||
is provided by the curl app in its read/write callbacks, and when doing
|
is provided by the curl app in its read/write callbacks, and when doing
|
||||||
-d/-F the callbacks aren't used!
|
-d/-F the callbacks aren't used! Bug report #921395.
|
||||||
|
|
||||||
* Doing resumed upload over HTTP does not work with '-C -', because curl
|
* Doing resumed upload over HTTP does not work with '-C -', because curl
|
||||||
doesn't do a HEAD first to get the initial size. This needs to be done
|
doesn't do a HEAD first to get the initial size. This needs to be done
|
||||||
|
|||||||
83
docs/LICENSE-MIXING
Normal file
83
docs/LICENSE-MIXING
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
License Mixing with apps, libcurl and Third Party Libraries
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
libcurl can be built to use a fair amount of various third party libraries,
|
||||||
|
libraries that are written and provided by other parties that are distributed
|
||||||
|
using their own licenses. Even libcurl itself contains code that may cause
|
||||||
|
problems to some. This document attempts to describe what licenses libcurl and
|
||||||
|
the other libraries use and what possible dilemmas linking and mixing them all
|
||||||
|
can lead to for end users.
|
||||||
|
|
||||||
|
I am not a lawyer and this is not legal advice!
|
||||||
|
|
||||||
|
One common dilemma is that GPL[*]-licensed code is not allowed to be linked
|
||||||
|
with code licensed under the Original BSD license (with the announcement
|
||||||
|
clause, unless there's a specified exception in the GPL-licensed module). You
|
||||||
|
may still build your own copies that use them all, but distributing them as
|
||||||
|
binaries would be to violate the GPL license. This particular problem was
|
||||||
|
addressed when the Modified BSD license was created, which does not have the
|
||||||
|
annoncement clause that collides with GPL.
|
||||||
|
|
||||||
|
libcurl http://curl.haxx.se/docs/copyright.html
|
||||||
|
|
||||||
|
Uses an MIT (or Modified BSD)-style license that is as liberal as
|
||||||
|
possible. Some of the source files that deal with KRB4 have Original
|
||||||
|
BSD-style announce-clause licenses. You may not distribute binaries
|
||||||
|
with krb4-enabled libcurl that also link with GPL-licensed code!
|
||||||
|
|
||||||
|
OpenSSL http://www.openssl.org/source/license.html
|
||||||
|
|
||||||
|
Uses an Original BSD-style license with an announement clause that
|
||||||
|
makes it "incompatible" with GPL. You are not allowed to ship binaries
|
||||||
|
that link with OpenSSL that includes GPL code (unless that specific
|
||||||
|
GPL code includes an exception for OpenSSL - a habit that is growing
|
||||||
|
more and more common).
|
||||||
|
|
||||||
|
c-ares http://daniel.haxx.se/projects/c-ares/license.html
|
||||||
|
|
||||||
|
Uses an MIT license that is very liberal and imposes no restrictions
|
||||||
|
on any other library or part you may link with.
|
||||||
|
|
||||||
|
zlib http://www.gzip.org/zlib/zlib_license.html
|
||||||
|
|
||||||
|
Uses an MIT-style license that shouldn't collide with any other
|
||||||
|
library.
|
||||||
|
|
||||||
|
krb4
|
||||||
|
|
||||||
|
While nothing in particular says that a Kerberos4 library must use any
|
||||||
|
particular license, the one I've tried and used successfully so far
|
||||||
|
(kth-krb4) is Original BSD-licensed with the announcement clause. Some
|
||||||
|
of the code in libcurl that is written to deal with Kerberos4 likewise
|
||||||
|
have such a license.
|
||||||
|
|
||||||
|
GSSAPI
|
||||||
|
|
||||||
|
While nothing in particular says that a GSS/Kerberos5 library must use
|
||||||
|
any particular license, the one I've used (Heimdal) is Original BSD-
|
||||||
|
licensed with the announcement clause.
|
||||||
|
|
||||||
|
fbopenssl
|
||||||
|
|
||||||
|
Unclear license. Based on its name, I assume that it uses the OpenSSL
|
||||||
|
license and thus shares the same issues as described for OpenSSL
|
||||||
|
above.
|
||||||
|
|
||||||
|
libidn http://www.gnu.org/licenses/lgpl.html
|
||||||
|
|
||||||
|
Uses the GNU Lesser General Public License. LGPL is a variation of GPL
|
||||||
|
with slightly less aggressive "copyleft". This license requires more
|
||||||
|
requirements to be met when distributing binaries, see the license for
|
||||||
|
details. Also note that if you distribute a binary that includes this
|
||||||
|
library, you must also include the full LGPL license text. Please
|
||||||
|
properly point out what parts of the distributed package that the
|
||||||
|
license addresses.
|
||||||
|
|
||||||
|
OpenLDAP http://www.openldap.org/software/release/license.html
|
||||||
|
|
||||||
|
Uses a Modified BSD-style license. Since libcurl uses OpenLDAP as a
|
||||||
|
shared library only, I have not heard of anyone that ships OpenLDAP
|
||||||
|
linked with libcurl in an app.
|
||||||
|
|
||||||
|
|
||||||
|
[*] = GPL - GNU General Public License: http://www.gnu.org/licenses/gpl.html
|
||||||
@@ -4,28 +4,20 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||||
|
|
||||||
man_MANS = \
|
man_MANS = curl.1 curl-config.1
|
||||||
curl.1 \
|
GENHTMLPAGES = curl.html curl-config.html
|
||||||
curl-config.1
|
PDFPAGES = curl.pdf curl-config.pdf
|
||||||
|
|
||||||
GENHTMLPAGES = \
|
|
||||||
curl.html \
|
|
||||||
curl-config.html
|
|
||||||
|
|
||||||
HTMLPAGES = $(GENHTMLPAGES) index.html
|
HTMLPAGES = $(GENHTMLPAGES) index.html
|
||||||
|
|
||||||
PDFPAGES = \
|
|
||||||
curl.pdf \
|
|
||||||
curl-config.pdf
|
|
||||||
|
|
||||||
SUBDIRS = examples libcurl
|
SUBDIRS = examples libcurl
|
||||||
|
|
||||||
CLEANFILES = $(GENHTMLPAGES) $(PDFPAGES)
|
CLEANFILES = $(GENHTMLPAGES) $(PDFPAGES)
|
||||||
|
|
||||||
EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
|
EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
|
||||||
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS \
|
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
|
||||||
VERSIONS KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) \
|
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
|
||||||
HISTORY INSTALL libcurl-the-guide $(PDFPAGES)
|
libcurl-the-guide $(PDFPAGES) LICENSE-MIXING
|
||||||
|
|
||||||
MAN2HTML= roffit < $< >$@
|
MAN2HTML= roffit < $< >$@
|
||||||
|
|
||||||
|
|||||||
31
docs/TODO
31
docs/TODO
@@ -36,6 +36,10 @@ TODO
|
|||||||
* Option to set the SO_KEEPALIVE socket option to make libcurl notice and
|
* Option to set the SO_KEEPALIVE socket option to make libcurl notice and
|
||||||
disconnect very long time idle connections.
|
disconnect very long time idle connections.
|
||||||
|
|
||||||
|
* When posting multipart forms, we should _not_ create the whole data chunk
|
||||||
|
in memory before the upload starts but do it in a "streaming" manner to
|
||||||
|
allow uploads that are way larger than the amount of system memory.
|
||||||
|
|
||||||
LIBCURL - multi interface
|
LIBCURL - multi interface
|
||||||
|
|
||||||
* Add curl_multi_timeout() to make libcurl's ares-functionality better.
|
* Add curl_multi_timeout() to make libcurl's ares-functionality better.
|
||||||
@@ -77,10 +81,16 @@ TODO
|
|||||||
* Since USERPWD always override the user and password specified in URLs, we
|
* Since USERPWD always override the user and password specified in URLs, we
|
||||||
might need another way to specify user+password for anonymous ftp logins.
|
might need another way to specify user+password for anonymous ftp logins.
|
||||||
|
|
||||||
|
* The FTP code should get a way of returning errors that is known to still
|
||||||
|
have the control connection alive and sound. Currently, a returned error
|
||||||
|
from within ftp-functions does not tell if the control connection is still
|
||||||
|
OK to use or not. This causes libcurl to fail to re-use connections
|
||||||
|
slightly too often.
|
||||||
|
|
||||||
HTTP
|
HTTP
|
||||||
|
|
||||||
* Digest and GSS-Negotiate support for HTTP proxies. They only work on
|
* GSS-Negotiate support for HTTP proxies. They only work on direct
|
||||||
direct-connections to the server.
|
connections to the server.
|
||||||
|
|
||||||
* Pipelining. Sending multiple requests before the previous one(s) are done.
|
* Pipelining. Sending multiple requests before the previous one(s) are done.
|
||||||
This could possibly be implemented using the multi interface to queue
|
This could possibly be implemented using the multi interface to queue
|
||||||
@@ -104,9 +114,6 @@ TODO
|
|||||||
* Evaluate/apply Gertjan van Wingerde's SSL patches:
|
* Evaluate/apply Gertjan van Wingerde's SSL patches:
|
||||||
http://curl.haxx.se/mail/lib-2004-03/0087.html
|
http://curl.haxx.se/mail/lib-2004-03/0087.html
|
||||||
|
|
||||||
* Peter Sylvester's "Most Significant Common Name" change. Feedback welcome.
|
|
||||||
At least the UTF8 conversion and comparison should be done. Patch?
|
|
||||||
|
|
||||||
* If you really want to improve the SSL situation, you should probably have a
|
* 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
|
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
|
done on every request as well, when they should only be necessary once per
|
||||||
@@ -174,6 +181,18 @@ TODO
|
|||||||
* --data-encode that URL encodes the data before posting
|
* --data-encode that URL encodes the data before posting
|
||||||
http://curl.haxx.se/mail/archive-2003-11/0091.html (Kevin Roth suggested)
|
http://curl.haxx.se/mail/archive-2003-11/0091.html (Kevin Roth suggested)
|
||||||
|
|
||||||
|
* Provide a way to make options bound to a specific URL among several on the
|
||||||
|
command line. Possibly by adding a new option that separates options
|
||||||
|
between URLs, similar to this:
|
||||||
|
|
||||||
|
curl --data foo --url url.com --optionseparator
|
||||||
|
--url url2.com --optionseparator \
|
||||||
|
--url url3.com --data foo3
|
||||||
|
|
||||||
|
(--optionseparator used to show my point, it would need a better name)
|
||||||
|
|
||||||
|
The example would do a POST-GET-POST combination on a single command line.
|
||||||
|
|
||||||
BUILD
|
BUILD
|
||||||
|
|
||||||
* Consider extending 'roffit' to produce decent ASCII output, and use that
|
* Consider extending 'roffit' to produce decent ASCII output, and use that
|
||||||
@@ -201,8 +220,6 @@ TODO
|
|||||||
* curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a
|
* curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a
|
||||||
CURLMcode. These should be changed to be the same.
|
CURLMcode. These should be changed to be the same.
|
||||||
|
|
||||||
* curl_formparse() should be removed
|
|
||||||
|
|
||||||
* remove obsolete defines from curl/curl.h
|
* remove obsolete defines from curl/curl.h
|
||||||
|
|
||||||
* remove the following functions from the public API:
|
* remove the following functions from the public API:
|
||||||
|
|||||||
60
docs/curl.1
60
docs/curl.1
@@ -1,8 +1,27 @@
|
|||||||
.\" You can view this file with:
|
.\" **************************************************************************
|
||||||
.\" nroff -man curl.1
|
.\" * _ _ ____ _
|
||||||
.\" Written by Daniel Stenberg
|
.\" * Project ___| | | | _ \| |
|
||||||
|
.\" * / __| | | | |_) | |
|
||||||
|
.\" * | (__| |_| | _ <| |___
|
||||||
|
.\" * \___|\___/|_| \_\_____|
|
||||||
|
.\" *
|
||||||
|
.\" * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
.\" *
|
||||||
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
|
.\" * you should have received as part of this distribution. The terms
|
||||||
|
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
.\" *
|
||||||
|
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
.\" * copies of the Software, and permit persons to whom the Software is
|
||||||
|
.\" * furnished to do so, under the terms of the COPYING file.
|
||||||
|
.\" *
|
||||||
|
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
.\" * KIND, either express or implied.
|
||||||
|
.\" *
|
||||||
|
.\" * $Id$
|
||||||
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH curl 1 "25 Mar 2004" "Curl 7.11.2" "Curl Manual"
|
.TH curl 1 "3 May 2004" "Curl 7.12" "Curl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl \- transfer a URL
|
curl \- transfer a URL
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -37,9 +56,10 @@ or you can get sequences of alphanumeric series by using [] as in:
|
|||||||
ftp://ftp.numericals.com/file[001-100].txt (with leading zeros)
|
ftp://ftp.numericals.com/file[001-100].txt (with leading zeros)
|
||||||
ftp://ftp.letters.com/file[a-z].txt
|
ftp://ftp.letters.com/file[a-z].txt
|
||||||
|
|
||||||
No nesting of the sequences is supported at the moment:
|
No nesting of the sequences is supported at the moment, but you can use
|
||||||
|
several ones next to each other:
|
||||||
|
|
||||||
http://www.any.org/archive[1996-1999]/volume[1-4]part{a,b,c,index}.html
|
http://any.org/archive[1996-1999]/vol[1-4]/part{a,b,c}.html
|
||||||
|
|
||||||
You can specify any amount of URLs on the command line. They will be fetched
|
You can specify any amount of URLs on the command line. They will be fetched
|
||||||
in a sequential manner in the specified order.
|
in a sequential manner in the specified order.
|
||||||
@@ -123,7 +143,7 @@ If this option is used several times, each occurrence will toggle it on/off.
|
|||||||
.IP "--connect-timeout <seconds>"
|
.IP "--connect-timeout <seconds>"
|
||||||
Maximum time in seconds that you allow the connection to the server to take.
|
Maximum time in seconds that you allow the connection to the server to take.
|
||||||
This only limits the connection phase, once curl has connected this option is
|
This only limits the connection phase, once curl has connected this option is
|
||||||
of no more use. See also the \fI--max-time\fP option.
|
of no more use. See also the \fI-m/--max-time\fP option.
|
||||||
|
|
||||||
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 "-c/--cookie-jar <file name>"
|
.IP "-c/--cookie-jar <file name>"
|
||||||
@@ -153,8 +173,12 @@ 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 "--create-dirs"
|
.IP "--create-dirs"
|
||||||
When used in conjunction with the -o option, curl will create the necessary
|
When used in conjunction with the -o option, curl will create the necessary
|
||||||
local directory hierarchy as needed.
|
local directory hierarchy as needed. This option creates the dirs mentioned
|
||||||
|
with the -o option, nothing else. If the -o file name uses no dir or if the
|
||||||
|
dirs it mentions already exist, no dir will be created.
|
||||||
|
|
||||||
|
To create remote directories when using FTP, try \fI--ftp-create-dirs\fP.
|
||||||
.IP "--crlf"
|
.IP "--crlf"
|
||||||
(FTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).
|
(FTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).
|
||||||
|
|
||||||
@@ -589,11 +613,23 @@ You may use this option as many times as you have number of URLs.
|
|||||||
(SSL) Pass phrase for the private key
|
(SSL) Pass phrase for the private key
|
||||||
|
|
||||||
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 "--proxy-basic"
|
||||||
|
Tells curl to use HTTP Basic authentication when communicating with the given
|
||||||
|
proxy. Use \fI--basic\fP for enabling HTTP Basic with a remote host. Basic is
|
||||||
|
the default authentication method curl uses with proxies.
|
||||||
|
|
||||||
|
If this option is used twice, the second will again disable proxy HTTP Basic
|
||||||
|
authentication.
|
||||||
|
.IP "--proxy-digest"
|
||||||
|
Tells curl to use HTTP Digest authentication when communicating with the given
|
||||||
|
proxy. Use \fI--digest\fP for enabling HTTP Digest with a remote host.
|
||||||
|
|
||||||
|
If this option is used twice, the second will again disable proxy HTTP Digest.
|
||||||
.IP "--proxy-ntlm"
|
.IP "--proxy-ntlm"
|
||||||
Tells curl to use NTLM authentication when communicating with the given
|
Tells curl to use HTTP NTLM authentication when communicating with the given
|
||||||
proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host.
|
proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host.
|
||||||
|
|
||||||
If this option is used twice, the second will again disable proxy NTLM.
|
If this option is used twice, the second will again disable proxy HTTP NTLM.
|
||||||
.IP "-p/--proxytunnel"
|
.IP "-p/--proxytunnel"
|
||||||
When an HTTP proxy is used (\fI-x/--proxy\fP), this option will cause non-HTTP
|
When an HTTP proxy is used (\fI-x/--proxy\fP), this option will cause non-HTTP
|
||||||
protocols to attempt to tunnel through the proxy instead of merely using it to
|
protocols to attempt to tunnel through the proxy instead of merely using it to
|
||||||
@@ -821,6 +857,8 @@ This curl uses asynchronous name resolves.
|
|||||||
SPNEGO Negotiate authenticaion is supported.
|
SPNEGO Negotiate authenticaion is supported.
|
||||||
.IP "Largefile"
|
.IP "Largefile"
|
||||||
This curl supports transfers of large files, files larger than 2GB.
|
This curl supports transfers of large files, files larger than 2GB.
|
||||||
|
.IP "IDN"
|
||||||
|
This curl supports IDN - international domain names.
|
||||||
.RE
|
.RE
|
||||||
.IP "-w/--write-out <format>"
|
.IP "-w/--write-out <format>"
|
||||||
Defines what to display after a completed and successful operation. The format
|
Defines what to display after a completed and successful operation. The format
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||||
|
|
||||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
||||||
persistant.c ftpget.c Makefile.example \
|
persistant.c ftpget.c Makefile.example multithread.c getinmemory.c \
|
||||||
multithread.c getinmemory.c ftpupload.c httpput.c \
|
ftpupload.c httpput.c simplessl.c ftpgetresp.c http-post.c \
|
||||||
simplessl.c ftpgetresp.c http-post.c post-callback.c \
|
post-callback.c multi-app.c multi-double.c multi-single.c \
|
||||||
multi-app.c multi-double.c multi-single.c multi-post.c \
|
multi-post.c fopen.c simplepost.c makefile.dj curlx.c https.c \
|
||||||
fopen.c simplepost.c makefile.dj curlx.c
|
multi-debugcallback.c fileupload.c
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@echo "done"
|
@echo "done"
|
||||||
|
|||||||
65
docs/examples/fileupload.c
Normal file
65
docs/examples/fileupload.c
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
curl_off_t size;
|
||||||
|
struct stat file_info;
|
||||||
|
double speed_upload, total_time;
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
fd = fopen("debugit", "r"); /* open file to upload */
|
||||||
|
if(!fd) {
|
||||||
|
|
||||||
|
return 1; /* can't continue */
|
||||||
|
}
|
||||||
|
|
||||||
|
stat("debugit", &file_info); /* to get the file size */
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
/* upload to this place */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL,
|
||||||
|
"file:///home/dast/src/curl/debug/new");
|
||||||
|
|
||||||
|
/* tell it to "upload" to the URL */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
||||||
|
|
||||||
|
/* set where to read from (on Windows you need to use READFUNCTION too) */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
|
||||||
|
|
||||||
|
/* and give the size of the upload (optional) */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
|
||||||
|
(curl_off_t)file_info.st_size);
|
||||||
|
|
||||||
|
/* enable verbose for easier tracing */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* now extract transfer info */
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload);
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time);
|
||||||
|
|
||||||
|
fprintf(stderr, "Speed: %.3f bytes/sec during %.3f seconds\n",
|
||||||
|
speed_upload, total_time);
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
@@ -46,7 +46,7 @@ int main(int argc, char **argv)
|
|||||||
close(hd) ;
|
close(hd) ;
|
||||||
|
|
||||||
/* get a FILE * of the same file, could also be made with
|
/* get a FILE * of the same file, could also be made with
|
||||||
fdopen() from the previous descriptor, but hey this is just
|
fdopen() from the previous descriptor, but hey this is just
|
||||||
an example! */
|
an example! */
|
||||||
hd_src = fopen(LOCAL_FILE, "rb");
|
hd_src = fopen(LOCAL_FILE, "rb");
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ int main(int argc, char **argv)
|
|||||||
/* we pass our 'chunk' struct to the callback function */
|
/* we pass our 'chunk' struct to the callback function */
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||||
|
|
||||||
|
/* some servers don't like requests that are made without a user-agent
|
||||||
|
field, so we provide one */
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||||
|
|
||||||
/* get it! */
|
/* get it! */
|
||||||
curl_easy_perform(curl_handle);
|
curl_easy_perform(curl_handle);
|
||||||
|
|
||||||
|
|||||||
53
docs/examples/https.c
Normal file
53
docs/examples/https.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "https://sourceforge.net/");
|
||||||
|
|
||||||
|
#ifdef SKIP_PEER_VERIFICATION
|
||||||
|
/*
|
||||||
|
* If you want to connect to a site who isn't using a certificate that is
|
||||||
|
* signed by one of the certs in the CA bundle you have, you can skip the
|
||||||
|
* verification of the server's certificate. This makes the connection
|
||||||
|
* A LOT LESS SECURE.
|
||||||
|
*
|
||||||
|
* If you have a CA cert for the server stored someplace else than in the
|
||||||
|
* default bundle, then the CURLOPT_CAPATH option might come handy for
|
||||||
|
* you.
|
||||||
|
*/
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SKIP_HOSTNAME_VERFICATION
|
||||||
|
/*
|
||||||
|
* If the site you're connecting to uses a different host name that what
|
||||||
|
* they have mentioned in their server certificate's commonName (or
|
||||||
|
* subjectAltName) fields, libcurl will refuse to connect. You can skip
|
||||||
|
* this check, but this will make the connection less secure.
|
||||||
|
*/
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
178
docs/examples/multi-debugcallback.c
Normal file
178
docs/examples/multi-debugcallback.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* This is a very simple example using the multi interface and the debug
|
||||||
|
* callback.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* somewhat unix-specific */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* curl stuff */
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
typedef char bool;
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
static
|
||||||
|
void dump(const char *text,
|
||||||
|
FILE *stream, unsigned char *ptr, size_t size,
|
||||||
|
bool nohex)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
unsigned int width=0x10;
|
||||||
|
|
||||||
|
if(nohex)
|
||||||
|
/* without the hex output, we can fit more on screen */
|
||||||
|
width = 0x40;
|
||||||
|
|
||||||
|
fprintf(stream, "%s, %zd bytes (0x%zx)\n", text, size, size);
|
||||||
|
|
||||||
|
for(i=0; i<size; i+= width) {
|
||||||
|
|
||||||
|
fprintf(stream, "%04zx: ", i);
|
||||||
|
|
||||||
|
if(!nohex) {
|
||||||
|
/* hex not disabled, show it */
|
||||||
|
for(c = 0; c < width; c++)
|
||||||
|
if(i+c < size)
|
||||||
|
fprintf(stream, "%02x ", ptr[i+c]);
|
||||||
|
else
|
||||||
|
fputs(" ", stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(c = 0; (c < width) && (i+c < size); c++) {
|
||||||
|
/* check for 0D0A; if found, skip past and start a new line of output */
|
||||||
|
if (nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
|
||||||
|
i+=(c+2-width);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stream, "%c",
|
||||||
|
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
|
||||||
|
/* check again for 0D0A, to avoid an extra \n if it's at width */
|
||||||
|
if (nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
|
||||||
|
i+=(c+3-width);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc('\n', stream); /* newline */
|
||||||
|
}
|
||||||
|
fflush(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int my_trace(CURL *handle, curl_infotype type,
|
||||||
|
unsigned char *data, size_t size,
|
||||||
|
void *userp)
|
||||||
|
{
|
||||||
|
const char *text;
|
||||||
|
|
||||||
|
(void)handle; /* prevent compiler warning */
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case CURLINFO_TEXT:
|
||||||
|
fprintf(stderr, "== Info: %s", data);
|
||||||
|
default: /* in case a new one is introduced to shock us */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case CURLINFO_HEADER_OUT:
|
||||||
|
text = "=> Send header";
|
||||||
|
break;
|
||||||
|
case CURLINFO_DATA_OUT:
|
||||||
|
text = "=> Send data";
|
||||||
|
break;
|
||||||
|
case CURLINFO_HEADER_IN:
|
||||||
|
text = "<= Recv header";
|
||||||
|
break;
|
||||||
|
case CURLINFO_DATA_IN:
|
||||||
|
text = "<= Recv data";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(text, stderr, data, size, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simply download a HTTP file.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *http_handle;
|
||||||
|
CURLM *multi_handle;
|
||||||
|
|
||||||
|
int still_running; /* keep number of running handles */
|
||||||
|
|
||||||
|
http_handle = curl_easy_init();
|
||||||
|
|
||||||
|
/* set the options (I left out a few, you'll get the point anyway) */
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.haxx.se/");
|
||||||
|
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_DEBUGFUNCTION, my_trace);
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_VERBOSE, TRUE);
|
||||||
|
|
||||||
|
/* init a multi stack */
|
||||||
|
multi_handle = curl_multi_init();
|
||||||
|
|
||||||
|
/* add the individual transfers */
|
||||||
|
curl_multi_add_handle(multi_handle, http_handle);
|
||||||
|
|
||||||
|
/* we start some action by calling perform right away */
|
||||||
|
while(CURLM_CALL_MULTI_PERFORM ==
|
||||||
|
curl_multi_perform(multi_handle, &still_running));
|
||||||
|
|
||||||
|
while(still_running) {
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc; /* select() return code */
|
||||||
|
|
||||||
|
fd_set fdread;
|
||||||
|
fd_set fdwrite;
|
||||||
|
fd_set fdexcep;
|
||||||
|
int maxfd;
|
||||||
|
|
||||||
|
FD_ZERO(&fdread);
|
||||||
|
FD_ZERO(&fdwrite);
|
||||||
|
FD_ZERO(&fdexcep);
|
||||||
|
|
||||||
|
/* set a suitable timeout to play around with */
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
/* get file descriptors from the transfers */
|
||||||
|
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||||
|
|
||||||
|
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||||
|
|
||||||
|
switch(rc) {
|
||||||
|
case -1:
|
||||||
|
/* select error */
|
||||||
|
still_running = 0;
|
||||||
|
printf("select() returns error, this is badness\n");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
/* timeout or readable/writable sockets */
|
||||||
|
while(CURLM_CALL_MULTI_PERFORM ==
|
||||||
|
curl_multi_perform(multi_handle, &still_running));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_multi_cleanup(multi_handle);
|
||||||
|
|
||||||
|
curl_easy_cleanup(http_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<HTML>
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
<HEAD>
|
<html><head>
|
||||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<TITLE>Index to Curl documentation</TITLE>
|
<title>Index to Curl documentation</title>
|
||||||
</HEAD>
|
</head>
|
||||||
|
|
||||||
<BODY>
|
<body>
|
||||||
<H1 ALIGN="CENTER">Index to Curl documentation</H1>
|
<h1 align="center">Index to Curl documentation</h1>
|
||||||
|
|
||||||
<H2>Programs</H2>
|
<h2>Programs</h2>
|
||||||
<a href="curl-config.html">curl-config</A>
|
<a href="curl-config.html">curl-config</A>
|
||||||
<br><a href="curl.html">curl</A>
|
<br><a href="curl.html">curl</A>
|
||||||
|
|
||||||
@@ -17,5 +17,4 @@
|
|||||||
<h2>libcurl</h2>
|
<h2>libcurl</h2>
|
||||||
See the <a href="libcurl/index.html">libcurl section</a>
|
See the <a href="libcurl/index.html">libcurl section</a>
|
||||||
|
|
||||||
</BODY>
|
</body></html>
|
||||||
</HTML>
|
|
||||||
|
|||||||
@@ -4,119 +4,48 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||||
|
|
||||||
man_MANS = \
|
man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \
|
||||||
curl_easy_cleanup.3 \
|
curl_easy_perform.3 curl_easy_setopt.3 curl_easy_duphandle.3 \
|
||||||
curl_easy_getinfo.3 \
|
curl_formadd.3 curl_formfree.3 curl_getdate.3 curl_getenv.3 \
|
||||||
curl_easy_init.3 \
|
curl_slist_append.3 curl_slist_free_all.3 curl_version.3 \
|
||||||
curl_easy_perform.3 \
|
curl_version_info.3 curl_escape.3 curl_unescape.3 curl_free.3 \
|
||||||
curl_easy_setopt.3 \
|
curl_strequal.3 curl_mprintf.3 curl_global_init.3 \
|
||||||
curl_easy_duphandle.3 \
|
curl_global_cleanup.3 curl_multi_add_handle.3 curl_multi_cleanup.3 \
|
||||||
curl_formparse.3 \
|
curl_multi_fdset.3 curl_multi_info_read.3 curl_multi_init.3 \
|
||||||
curl_formadd.3 \
|
curl_multi_perform.3 curl_multi_remove_handle.3 curl_share_cleanup.3 \
|
||||||
curl_formfree.3 \
|
curl_share_init.3 curl_share_setopt.3 libcurl.3 libcurl-easy.3 \
|
||||||
curl_getdate.3 \
|
libcurl-multi.3 libcurl-share.3 libcurl-errors.3 curl_easy_strerror.3 \
|
||||||
curl_getenv.3 \
|
curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3
|
||||||
curl_slist_append.3 \
|
|
||||||
curl_slist_free_all.3 \
|
|
||||||
curl_version.3 \
|
|
||||||
curl_version_info.3 \
|
|
||||||
curl_escape.3 \
|
|
||||||
curl_unescape.3 \
|
|
||||||
curl_free.3 \
|
|
||||||
curl_strequal.3 \
|
|
||||||
curl_strnequal.3 \
|
|
||||||
curl_mprintf.3 \
|
|
||||||
curl_global_init.3 \
|
|
||||||
curl_global_cleanup.3 \
|
|
||||||
curl_multi_add_handle.3 \
|
|
||||||
curl_multi_cleanup.3 \
|
|
||||||
curl_multi_fdset.3 \
|
|
||||||
curl_multi_info_read.3 \
|
|
||||||
curl_multi_init.3 \
|
|
||||||
curl_multi_perform.3 \
|
|
||||||
curl_multi_remove_handle.3 \
|
|
||||||
curl_share_cleanup.3 curl_share_init.3 curl_share_setopt.3 \
|
|
||||||
libcurl.3 \
|
|
||||||
libcurl-easy.3 \
|
|
||||||
libcurl-multi.3 \
|
|
||||||
libcurl-share.3 \
|
|
||||||
libcurl-errors.3
|
|
||||||
|
|
||||||
HTMLPAGES = \
|
HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
|
||||||
curl_easy_cleanup.html \
|
curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html \
|
||||||
curl_easy_getinfo.html \
|
curl_easy_duphandle.html curl_formadd.html curl_formfree.html \
|
||||||
curl_easy_init.html \
|
curl_getdate.html curl_getenv.html curl_slist_append.html \
|
||||||
curl_easy_perform.html \
|
curl_slist_free_all.html curl_version.html curl_version_info.html \
|
||||||
curl_easy_setopt.html \
|
curl_escape.html curl_unescape.html curl_free.html curl_strequal.html \
|
||||||
curl_easy_duphandle.html \
|
curl_mprintf.html curl_global_init.html curl_global_cleanup.html \
|
||||||
curl_formadd.html \
|
curl_multi_add_handle.html curl_multi_cleanup.html \
|
||||||
curl_formparse.html \
|
curl_multi_fdset.html curl_multi_info_read.html curl_multi_init.html \
|
||||||
curl_formfree.html \
|
curl_multi_perform.html curl_multi_remove_handle.html \
|
||||||
curl_getdate.html \
|
curl_share_cleanup.html curl_share_init.html curl_share_setopt.html \
|
||||||
curl_getenv.html \
|
libcurl.html libcurl-multi.html libcurl-easy.html libcurl-share.html \
|
||||||
curl_slist_append.html \
|
libcurl-errors.html curl_easy_strerror.html curl_multi_strerror.html \
|
||||||
curl_slist_free_all.html \
|
curl_share_strerror.html curl_global_init_mem.html
|
||||||
curl_version.html \
|
|
||||||
curl_version_info.html \
|
|
||||||
curl_escape.html \
|
|
||||||
curl_unescape.html \
|
|
||||||
curl_free.html \
|
|
||||||
curl_strequal.html \
|
|
||||||
curl_strnequal.html \
|
|
||||||
curl_mprintf.html \
|
|
||||||
curl_global_init.html \
|
|
||||||
curl_global_cleanup.html \
|
|
||||||
curl_multi_add_handle.html \
|
|
||||||
curl_multi_cleanup.html \
|
|
||||||
curl_multi_fdset.html \
|
|
||||||
curl_multi_info_read.html \
|
|
||||||
curl_multi_init.html \
|
|
||||||
curl_multi_perform.html \
|
|
||||||
curl_multi_remove_handle.html \
|
|
||||||
curl_share_cleanup.html curl_share_init.html curl_share_setopt.html \
|
|
||||||
libcurl.html \
|
|
||||||
libcurl-multi.html \
|
|
||||||
libcurl-easy.html \
|
|
||||||
libcurl-share.html \
|
|
||||||
libcurl-errors.html
|
|
||||||
|
|
||||||
PDFPAGES = \
|
PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
|
||||||
curl_easy_cleanup.pdf \
|
curl_easy_init.pdf curl_easy_perform.pdf curl_easy_setopt.pdf \
|
||||||
curl_easy_getinfo.pdf \
|
curl_easy_duphandle.pdf curl_formadd.pdf curl_formfree.pdf \
|
||||||
curl_easy_init.pdf \
|
curl_getdate.pdf curl_getenv.pdf curl_slist_append.pdf \
|
||||||
curl_easy_perform.pdf \
|
curl_slist_free_all.pdf curl_version.pdf curl_version_info.pdf \
|
||||||
curl_easy_setopt.pdf \
|
curl_escape.pdf curl_unescape.pdf curl_free.pdf curl_strequal.pdf \
|
||||||
curl_easy_duphandle.pdf \
|
curl_mprintf.pdf curl_global_init.pdf curl_global_cleanup.pdf \
|
||||||
curl_formadd.pdf \
|
curl_multi_add_handle.pdf curl_multi_cleanup.pdf curl_multi_fdset.pdf \
|
||||||
curl_formparse.pdf \
|
curl_multi_info_read.pdf curl_multi_init.pdf curl_multi_perform.pdf \
|
||||||
curl_formfree.pdf \
|
curl_multi_remove_handle.pdf curl_share_cleanup.pdf \
|
||||||
curl_getdate.pdf \
|
curl_share_init.pdf curl_share_setopt.pdf libcurl.pdf \
|
||||||
curl_getenv.pdf \
|
libcurl-multi.pdf libcurl-easy.pdf libcurl-share.pdf \
|
||||||
curl_slist_append.pdf \
|
libcurl-errors.pdf curl_easy_strerror.pdf curl_multi_strerror.pdf \
|
||||||
curl_slist_free_all.pdf \
|
curl_share_strerror.pdf curl_global_init_mem.pdf
|
||||||
curl_version.pdf \
|
|
||||||
curl_version_info.pdf \
|
|
||||||
curl_escape.pdf \
|
|
||||||
curl_unescape.pdf \
|
|
||||||
curl_free.pdf \
|
|
||||||
curl_strequal.pdf \
|
|
||||||
curl_strnequal.pdf \
|
|
||||||
curl_mprintf.pdf \
|
|
||||||
curl_global_init.pdf \
|
|
||||||
curl_global_cleanup.pdf \
|
|
||||||
curl_multi_add_handle.pdf \
|
|
||||||
curl_multi_cleanup.pdf \
|
|
||||||
curl_multi_fdset.pdf \
|
|
||||||
curl_multi_info_read.pdf \
|
|
||||||
curl_multi_init.pdf \
|
|
||||||
curl_multi_perform.pdf \
|
|
||||||
curl_multi_remove_handle.pdf \
|
|
||||||
curl_share_cleanup.pdf curl_share_init.pdf curl_share_setopt.pdf \
|
|
||||||
libcurl.pdf \
|
|
||||||
libcurl-multi.pdf \
|
|
||||||
libcurl-easy.pdf \
|
|
||||||
libcurl-share.pdf \
|
|
||||||
libcurl-errors.pdf
|
|
||||||
|
|
||||||
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
||||||
|
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ amortizes the overhead of the send. However, in some cases (most
|
|||||||
notably telnet or rlogin) small segments may need to be sent
|
notably telnet or rlogin) small segments may need to be sent
|
||||||
without delay. This is less efficient than sending larger amounts of
|
without delay. This is less efficient than sending larger amounts of
|
||||||
data at a time, and can contribute to congestion on the network if
|
data at a time, and can contribute to congestion on the network if
|
||||||
overdone.
|
overdone.
|
||||||
.SH NAMES and PASSWORDS OPTIONS (Authentication)
|
.SH NAMES and PASSWORDS OPTIONS (Authentication)
|
||||||
.IP CURLOPT_NETRC
|
.IP CURLOPT_NETRC
|
||||||
This parameter controls the preference of libcurl between using user names and
|
This parameter controls the preference of libcurl between using user names and
|
||||||
@@ -340,7 +340,7 @@ This value tells the library that use of the file is required,
|
|||||||
to ignore the information in the URL,
|
to ignore the information in the URL,
|
||||||
and to search the file with the host only.
|
and to search the file with the host only.
|
||||||
.RE
|
.RE
|
||||||
Only machine name, user name and password are taken into account
|
Only machine name, user name and password are taken into account
|
||||||
(init macros and similar things aren't supported).
|
(init macros and similar things aren't supported).
|
||||||
|
|
||||||
\fBNote:\fP libcurl does not verify that the file has the correct properties
|
\fBNote:\fP libcurl does not verify that the file has the correct properties
|
||||||
@@ -522,7 +522,7 @@ The first line in a request (usually containing a GET or POST) is not a header
|
|||||||
and cannot be replaced using this option. Only the lines following the
|
and cannot be replaced using this option. Only the lines following the
|
||||||
request-line are headers.
|
request-line are headers.
|
||||||
|
|
||||||
\fBNOTE:\fPThe most commonly replaced headers have "shortcuts" in the options
|
\fBNOTE:\fP The most commonly replaced headers have "shortcuts" in the options
|
||||||
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
|
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
|
||||||
.IP CURLOPT_HTTP200ALIASES
|
.IP CURLOPT_HTTP200ALIASES
|
||||||
Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
|
Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
|
||||||
@@ -535,7 +535,7 @@ The linked list should be a fully valid list of struct curl_slist structs, and
|
|||||||
be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
|
be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
|
||||||
\fIcurl_slist_free_all(3)\fP to clean up an entire list.
|
\fIcurl_slist_free_all(3)\fP to clean up an entire list.
|
||||||
|
|
||||||
\fBNOTE:\fPThe alias itself is not parsed for any version strings. So if your
|
\fBNOTE:\fP The alias itself is not parsed for any version strings. So if your
|
||||||
alias is "MYHTTP/9.9", Libcurl will not treat the server as responding with
|
alias is "MYHTTP/9.9", Libcurl will not treat the server as responding with
|
||||||
HTTP version 9.9. Instead Libcurl will use the value set by option
|
HTTP version 9.9. Instead Libcurl will use the value set by option
|
||||||
\fICURLOPT_HTTP_VERSION\fP.
|
\fICURLOPT_HTTP_VERSION\fP.
|
||||||
@@ -706,11 +706,11 @@ when doing an ftp directory listing. This is useful for doing DELETE or other
|
|||||||
more or less obscure HTTP requests. Don't do this at will, make sure your
|
more or less obscure HTTP requests. Don't do this at will, make sure your
|
||||||
server supports the command first.
|
server supports the command first.
|
||||||
|
|
||||||
NOTE: many people have wrongly used this option to replace the entire request
|
\fBNOTE:\fP Many people have wrongly used this option to replace the entire
|
||||||
with their own, including multiple headers and POST contents. While that might
|
request with their own, including multiple headers and POST contents. While
|
||||||
work in many cases, it will cause libcurl to send invalid requests and it
|
that might work in many cases, it will cause libcurl to send invalid requests
|
||||||
could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
|
and it could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP
|
||||||
\fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
|
and \fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
|
||||||
replace or extend the set of headers sent by libcurl. Use
|
replace or extend the set of headers sent by libcurl. Use
|
||||||
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
|
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
|
||||||
.IP CURLOPT_FILETIME
|
.IP CURLOPT_FILETIME
|
||||||
@@ -740,29 +740,29 @@ Pass a long as parameter. This allows you to specify the maximum size (in
|
|||||||
bytes) of a file to download. If the file requested is larger than this value,
|
bytes) of a file to download. If the file requested is larger than this value,
|
||||||
the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned.
|
the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned.
|
||||||
|
|
||||||
NOTE: The file size is not always known prior to download, and for such files
|
\fBNOTE:\fP The file size is not always known prior to download, and for such
|
||||||
this option has no effect even if the file transfer ends up being larger than
|
files this option has no effect even if the file transfer ends up being larger
|
||||||
this given limit. This concerns both FTP and HTTP transfers.
|
than this given limit. This concerns both FTP and HTTP transfers.
|
||||||
.IP CURLOPT_MAXFILESIZE_LARGE
|
.IP CURLOPT_MAXFILESIZE_LARGE
|
||||||
Pass a curl_off_t as parameter. This allows you to specify the maximum size
|
Pass a curl_off_t as parameter. This allows you to specify the maximum size
|
||||||
(in bytes) of a file to download. If the file requested is larger than this
|
(in bytes) of a file to download. If the file requested is larger than this
|
||||||
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
|
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
|
||||||
returned. (Added in 7.11.0)
|
returned. (Added in 7.11.0)
|
||||||
|
|
||||||
NOTE: The file size is not always known prior to download, and for such files
|
\fBNOTE:\fP The file size is not always known prior to download, and for such
|
||||||
this option has no effect even if the file transfer ends up being larger than
|
files this option has no effect even if the file transfer ends up being larger
|
||||||
this given limit. This concerns both FTP and HTTP transfers.
|
than this given limit. This concerns both FTP and HTTP transfers.
|
||||||
.IP CURLOPT_TIMECONDITION
|
.IP CURLOPT_TIMECONDITION
|
||||||
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
|
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
|
||||||
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
|
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
|
||||||
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
|
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
|
||||||
|
|
||||||
NOTE: The last modification time of a file is not always known and in such
|
\fBNOTE:\fP The last modification time of a file is not always known and in such
|
||||||
instances this feature will have no effect even if the given time condition
|
instances this feature will have no effect even if the given time condition
|
||||||
would have not been met.
|
would have not been met.
|
||||||
.IP CURLOPT_TIMEVALUE
|
.IP CURLOPT_TIMEVALUE
|
||||||
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
|
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
|
||||||
and the time will be used in a condition as specified with
|
and the time will be used in a condition as specified with
|
||||||
\fICURLOPT_TIMECONDITION\fP.
|
\fICURLOPT_TIMECONDITION\fP.
|
||||||
.SH CONNECTION OPTIONS
|
.SH CONNECTION OPTIONS
|
||||||
.IP CURLOPT_TIMEOUT
|
.IP CURLOPT_TIMEOUT
|
||||||
@@ -866,9 +866,10 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
|
|||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
||||||
|
|
||||||
\fBNOTE:\fPThe format "ENG" enables you to load the private key from a crypto
|
\fBNOTE:\fP The 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
|
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_SSLENGINE\fP.
|
the engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP.
|
||||||
|
\&"DER" format key file currently does not work because of a bug in OpenSSL.
|
||||||
.IP CURLOPT_SSLKEYPASSWD
|
.IP CURLOPT_SSLKEYPASSWD
|
||||||
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 \fICURLOPT_SSLKEY\fP private key.
|
the password required to use the \fICURLOPT_SSLKEY\fP private key.
|
||||||
@@ -877,13 +878,13 @@ 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
|
the identifier for the crypto engine you want to use for your private
|
||||||
key.
|
key.
|
||||||
|
|
||||||
\fBNOTE:\fPIf the crypto device cannot be loaded,
|
\fBNOTE:\fP If the crypto device cannot be loaded,
|
||||||
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned.
|
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned.
|
||||||
.IP CURLOPT_SSLENGINE_DEFAULT
|
.IP CURLOPT_SSLENGINE_DEFAULT
|
||||||
Sets the actual crypto engine as the default for (asymmetric) crypto
|
Sets the actual crypto engine as the default for (asymmetric) crypto
|
||||||
operations.
|
operations.
|
||||||
|
|
||||||
\fBNOTE:\fPIf the crypto device cannot be set,
|
\fBNOTE:\fP If the crypto device cannot be set,
|
||||||
\fICURLE_SSL_ENGINE_SETFAILED\fP is returned.
|
\fICURLE_SSL_ENGINE_SETFAILED\fP is returned.
|
||||||
.IP CURLOPT_SSLVERSION
|
.IP CURLOPT_SSLVERSION
|
||||||
Pass a long as parameter. Set what version of SSL to attempt to use, 2 or
|
Pass a long as parameter. Set what version of SSL to attempt to use, 2 or
|
||||||
|
|||||||
18
docs/libcurl/curl_easy_strerror.3
Normal file
18
docs/libcurl/curl_easy_strerror.3
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.\" You can view this file with:
|
||||||
|
.\" nroff -man [file]
|
||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.TH curl_easy_strerror 3 "26 Apr 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
|
.SH NAME
|
||||||
|
curl_easy_strerror - return string describing error code
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <curl/curl.h>
|
||||||
|
.BI "const char *curl_easy_strerror(CURLcode " errornum ");"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The curl_easy_strerror() function returns a string describing the CURLcode
|
||||||
|
error code passed in the argument \fIerrornum\fP.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
A pointer to a zero terminated string.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR libcurl-errors "(3), " curl_multi_strerror "(3), " curl_share_strerror "(3)"
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
.\" You can view this file with:
|
|
||||||
.\" nroff -man [file]
|
|
||||||
.\" $Id$
|
|
||||||
.\"
|
|
||||||
.TH curl_formparse 3 "17 Dec 2001" "libcurl 7.9.2" "libcurl Manual"
|
|
||||||
.SH NAME
|
|
||||||
curl_formparse - add a section to a multipart/formdata HTTP POST:
|
|
||||||
deprecated (use curl_formadd instead)
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B #include <curl/curl.h>
|
|
||||||
.sp
|
|
||||||
.BI "CURLcode curl_formparse(char * " string, " struct HttpPost ** " firstitem,
|
|
||||||
.BI "struct HttpPost ** " lastitem ");"
|
|
||||||
.ad
|
|
||||||
.SH DESCRIPTION
|
|
||||||
This has been removed deliberately. The \fBcurl_formadd\fP has been introduced
|
|
||||||
to replace this function. Do not use this. Convert to the new function
|
|
||||||
now. curl_formparse() will be removed from a future version of libcurl.
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
.\" You can view this file with:
|
|
||||||
.\" nroff -man [file]
|
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_getenv 3 "15 August 2001" "libcurl 7.8.1" "libcurl Manual"
|
.TH curl_getenv 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_getenv - return value for environment name
|
curl_getenv - return value for environment name
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -14,6 +12,10 @@ curl_getenv - return value for environment name
|
|||||||
curl_getenv() is a portable wrapper for the getenv() function, meant to
|
curl_getenv() is a portable wrapper for the getenv() function, meant to
|
||||||
emulate its behaviour and provide an identical interface for all operating
|
emulate its behaviour and provide an identical interface for all operating
|
||||||
systems libcurl builds on (including win32).
|
systems libcurl builds on (including win32).
|
||||||
|
.SH AVAILABILITY
|
||||||
|
This function will be removed from the public libcurl API in a near future. It
|
||||||
|
will instead be made "available" by source code access only, and then as
|
||||||
|
curlx_getenv().
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
If successful, curl_getenv() returns a pointer to the value of the specified
|
If successful, curl_getenv() returns a pointer to the value of the specified
|
||||||
environment. The memory it refers to is malloc()ed why the application must
|
environment. The memory it refers to is malloc()ed why the application must
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_global_init 3 "13 Nov 2001" "libcurl 7.9.1" "libcurl Manual"
|
.TH curl_global_init 3 "11 May 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_global_init - Global libcurl initialisation
|
curl_global_init - Global libcurl initialisation
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -42,6 +42,5 @@ Initialise nothing extra. This sets no bit.
|
|||||||
If this function returns non-zero, something went wrong and you cannot use the
|
If this function returns non-zero, something went wrong and you cannot use the
|
||||||
other curl functions.
|
other curl functions.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
.BR curl_global_init_mem "(3), "
|
||||||
.BR curl_global_cleanup "(3), "
|
.BR curl_global_cleanup "(3), "
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
42
docs/libcurl/curl_global_init_mem.3
Normal file
42
docs/libcurl/curl_global_init_mem.3
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.\" You can view this file with:
|
||||||
|
.\" nroff -man [file]
|
||||||
|
.\"
|
||||||
|
.TH curl_global_init_mem 3 "10 May 2004" "libcurl 7.12.0" "libcurl Manual"
|
||||||
|
.SH NAME
|
||||||
|
curl_global_init_mem - Global libcurl initialisation with memory callbacks
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B #include <curl/curl.h>
|
||||||
|
.nf
|
||||||
|
.B "CURLcode curl_global_init_mem(long " flags,
|
||||||
|
.B " curl_malloc_callback "m,
|
||||||
|
.B " curl_free_callback "f,
|
||||||
|
.B " curl_realloc_callback "r,
|
||||||
|
.B " curl_strdup_callback "s,
|
||||||
|
.B " curl_calloc_callback "c ");"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This function works exactly as \fIcurl_global_init(3)\fP with one addition: it
|
||||||
|
allows the application to set callbacks to replace the otherwise used internal
|
||||||
|
memory functions.
|
||||||
|
|
||||||
|
This man page only adds documentation for the callbacks, see the
|
||||||
|
\fIcurl_global_init(3)\fP man page for all the rest. When you use this
|
||||||
|
function, all callback arguments must be set to valid function pointers.
|
||||||
|
|
||||||
|
The prototypes for the given callbacks should match these:
|
||||||
|
.IP "void *malloc_callback(size_t size);"
|
||||||
|
To replace malloc()
|
||||||
|
.IP "void free_callback(void *ptr);"
|
||||||
|
To replace free()
|
||||||
|
.IP "void *realloc_callback(void *ptr, size_t size);"
|
||||||
|
To replace realloc()
|
||||||
|
.IP "char *strdup_callback(const char *str);"
|
||||||
|
To replace strdup()
|
||||||
|
.IP "void *calloc_callback(size_t nmemb, size_t size);"
|
||||||
|
To replace calloc()
|
||||||
|
.SH "CAUTION"
|
||||||
|
Manipulating these gives considerable powers to the application to severly
|
||||||
|
screw things up for libcurl. Take care!
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR curl_global_init "(3), "
|
||||||
|
.BR curl_global_cleanup "(3), "
|
||||||
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
.\" You can view this file with:
|
|
||||||
.\" nroff -man [file]
|
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_printf 3 "20 April 2001" "libcurl 7.7.2" "libcurl Manual"
|
.TH curl_printf 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
|
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
|
||||||
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
|
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
|
||||||
@@ -79,6 +77,10 @@ To easily use all these cloned functions instead of the normal ones, #define
|
|||||||
_MPRINTF_REPLACE before you include the <curl/mprintf.h> file. Then all the
|
_MPRINTF_REPLACE before you include the <curl/mprintf.h> file. Then all the
|
||||||
normal names like printf, fprintf, sprintf etc will use the curl-functions
|
normal names like printf, fprintf, sprintf etc will use the curl-functions
|
||||||
instead.
|
instead.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
These function will be removed from the public libcurl API in a near
|
||||||
|
future. They will instead be made "available" by source code access only, and
|
||||||
|
then as curlx_-prefixed functions. See lib/README.curlx for further details.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
The \fBcurl_maprintf\fP and \fBcurl_mvaprintf\fP functions return a pointer to
|
The \fBcurl_maprintf\fP and \fBcurl_mvaprintf\fP functions return a pointer to
|
||||||
a newly allocated string, or NULL it it failed.
|
a newly allocated string, or NULL it it failed.
|
||||||
|
|||||||
18
docs/libcurl/curl_multi_strerror.3
Normal file
18
docs/libcurl/curl_multi_strerror.3
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.\" You can view this file with:
|
||||||
|
.\" nroff -man [file]
|
||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.TH curl_multi_strerror 3 "26 Apr 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
|
.SH NAME
|
||||||
|
curl_multi_strerror - return string describing error code
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <curl/curl.h>
|
||||||
|
.BI "const char *curl_multi_strerror(CURLMcode " errornum ");"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The curl_multi_strerror() function returns a string describing the CURLMcode
|
||||||
|
error code passed in the argument \fIerrornum\fP.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
A pointer to a zero terminated string.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR libcurl-errors "(3), " curl_easy_strerror "(3), " curl_share_strerror "(3)"
|
||||||
18
docs/libcurl/curl_share_strerror.3
Normal file
18
docs/libcurl/curl_share_strerror.3
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.\" You can view this file with:
|
||||||
|
.\" nroff -man [file]
|
||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.TH curl_share_strerror 3 "26 Apr 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
|
.SH NAME
|
||||||
|
curl_share_strerror - return string describing error code
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <curl/curl.h>
|
||||||
|
.BI "const char *curl_share_strerror(CURLSHcode " errornum ");"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The curl_share_strerror() function returns a string describing the CURLSHcode
|
||||||
|
error code passed in the argument \fIerrornum\fP.
|
||||||
|
.SH RETURN VALUE
|
||||||
|
A pointer to a zero terminated string.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR libcurl-errors "(3), " curl_multi_strerror "(3), " curl_easy_strerror "(3)"
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
.\" You can view this file with:
|
|
||||||
.\" nroff -man [file]
|
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_strequal 3 "20 April 2001" "libcurl 7.7.2" "libcurl Manual"
|
.TH curl_strequal 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_strequal, curl_strnequal - case insensitive string comparisons
|
curl_strequal, curl_strnequal - case insensitive string comparisons
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -24,6 +22,10 @@ first \fIlen\fP characters of \fIstr1\fP.
|
|||||||
These functions are provided by libcurl to enable applications to compare
|
These functions are provided by libcurl to enable applications to compare
|
||||||
strings in a truly portable manner. There are no standard portable case
|
strings in a truly portable manner. There are no standard portable case
|
||||||
insensitive string comparison functions. These two works on all platforms.
|
insensitive string comparison functions. These two works on all platforms.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
These functions will be removed from the public libcurl API in a near
|
||||||
|
future. They will instead be made "available" by source code access only, and
|
||||||
|
then as curlx_strequal() and curlx_strenqual().
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Non-zero if the strings are identical. Zero if they're not.
|
Non-zero if the strings are identical. Zero if they're not.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ curl_unescape - URL decodes the given string
|
|||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This function will convert the given URL encoded input string to a "plain
|
This function will convert the given URL encoded input string to a "plain
|
||||||
string" and return that as a new allocated string. All input characters that
|
string" and return that as a new allocated string. All input characters that
|
||||||
are URL encoded (%XX where XX is a two-digit hexadecimal number, or +) will be
|
are URL encoded (%XX where XX is a two-digit hexadecimal number) will be
|
||||||
converted to their plain text versions (up to a ? letter, no + letters to the
|
converted to their plain text versions.
|
||||||
right of a ? letter will be converted).
|
|
||||||
|
|
||||||
If the 'length' argument is set to 0, curl_unescape() will use strlen() on the
|
If the 'length' argument is set to 0, curl_unescape() will use strlen() on the
|
||||||
input 'url' string to find out the size.
|
input 'url' string to find out the size.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_version_info 3 "19 Sep 2003" "libcurl 7.10.8" "libcurl Manual"
|
.TH curl_version_info 3 "11 May 2004" "libcurl 7.12" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_version_info - returns run-time libcurl version info
|
curl_version_info - returns run-time libcurl version info
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -28,22 +28,32 @@ The curl_version_info_data struct looks like this
|
|||||||
|
|
||||||
.nf
|
.nf
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CURLversion age; /* 0 - this kind of struct */
|
CURLversion age; /* see description below */
|
||||||
|
|
||||||
|
/* when 'age' is 0 or higher, the members below also exist: */
|
||||||
const char *version; /* human readable string */
|
const char *version; /* human readable string */
|
||||||
unsigned int version_num; /* numeric representation */
|
unsigned int version_num; /* numeric representation */
|
||||||
const char *host; /* human readable string */
|
const char *host; /* human readable string */
|
||||||
int features; /* bitmask, see below */
|
int features; /* bitmask, see below */
|
||||||
char *ssl_version; /* human readable string */
|
char *ssl_version; /* human readable string */
|
||||||
long ssl_version_num; /* number */
|
long ssl_version_num; /* number */
|
||||||
char *libz_version; /* human readable string */
|
const char *libz_version; /* human readable string */
|
||||||
const char *protocols[]; /* list of protocols */
|
const char **protocols; /* list of protocols */
|
||||||
|
|
||||||
|
/* when 'age' is 1 or higher, the members below also exist: */
|
||||||
|
const char *ares; /* human readable string */
|
||||||
|
int ares_num; /* number */
|
||||||
|
|
||||||
|
/* when 'age' is 2 or higher, the member below also exists: */
|
||||||
|
const char *libidn; /* human readable string */
|
||||||
|
|
||||||
} curl_version_info_data;
|
} curl_version_info_data;
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
\fIage\fP describes what kind of struct this is. It is always 0 now. In a
|
\fIage\fP describes what age of this struct this is. The number depends on how
|
||||||
future libcurl, if this struct changes, this age counter may be increased, and
|
new libcurl you're using. You are however guaranteed to get a struct that you
|
||||||
then the struct for number 1 will look different (except for this first struct
|
have a matching struct for in the header, as you tell libcurl your "age" with
|
||||||
field).
|
the input argument.
|
||||||
|
|
||||||
\fIversion\fP is just an ascii string for the libcurl version.
|
\fIversion\fP is just an ascii string for the libcurl version.
|
||||||
|
|
||||||
@@ -57,38 +67,35 @@ environment.
|
|||||||
|
|
||||||
\fIfeatures\fP can have none, one or more bits set, and the currently defined
|
\fIfeatures\fP can have none, one or more bits set, and the currently defined
|
||||||
bits are:
|
bits are:
|
||||||
.TP 5.5
|
.RS
|
||||||
.B CURL_VERSION_IPV6
|
.IP CURL_VERSION_IPV6
|
||||||
supports IPv6
|
supports IPv6
|
||||||
.TP
|
.IP CURL_VERSION_KERBEROS4
|
||||||
.B CURL_VERSION_KERBEROS4
|
|
||||||
supports kerberos4 (when using FTP)
|
supports kerberos4 (when using FTP)
|
||||||
.TP
|
.IP CURL_VERSION_SSL
|
||||||
.B CURL_VERSION_SSL
|
|
||||||
supports SSL (HTTPS/FTPS)
|
supports SSL (HTTPS/FTPS)
|
||||||
.TP
|
.IP CURL_VERSION_LIBZ
|
||||||
.B CURL_VERSION_LIBZ
|
|
||||||
supports HTTP deflate using libz
|
supports HTTP deflate using libz
|
||||||
.TP
|
.IP CURL_VERSION_NTLM
|
||||||
.B CURL_VERSION_NTLM
|
|
||||||
supports HTTP NTLM (added in 7.10.6)
|
supports HTTP NTLM (added in 7.10.6)
|
||||||
.TP
|
.IP CURL_VERSION_GSSNEGOTIATE
|
||||||
.B CURL_VERSION_GSSNEGOTIATE
|
|
||||||
supports HTTP GSS-Negotiate (added in 7.10.6)
|
supports HTTP GSS-Negotiate (added in 7.10.6)
|
||||||
.TP
|
.IP CURL_VERSION_DEBUG
|
||||||
.B CURL_VERSION_DEBUG
|
|
||||||
libcurl was built with extra debug capabilities built-in. This is mainly of
|
libcurl was built with extra debug capabilities built-in. This is mainly of
|
||||||
interest for libcurl hackers. (added in 7.10.6)
|
interest for libcurl hackers. (added in 7.10.6)
|
||||||
.TP
|
.IP CURL_VERSION_ASYNCHDNS
|
||||||
.B CURL_VERSION_ASYNCHDNS
|
|
||||||
libcurl was built with support for asynchronous name lookups, which allows
|
libcurl was built with support for asynchronous name lookups, which allows
|
||||||
more exact timeouts (even on Windows) and less blocking when using the multi
|
more exact timeouts (even on Windows) and less blocking when using the multi
|
||||||
interface. (added in 7.10.7)
|
interface. (added in 7.10.7)
|
||||||
.TP
|
.IP CURL_VERSION_SPNEGO
|
||||||
.B CURL_VERSION_SPNEGO
|
|
||||||
libcurl was built with support for SPNEGO authentication (Simple and Protected
|
libcurl was built with support for SPNEGO authentication (Simple and Protected
|
||||||
GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
|
GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
|
||||||
.PP
|
.IP CURL_VERSION_LARGEFILE
|
||||||
|
libcurl was built with support for large files.
|
||||||
|
.IP CURL_VERSION_IDN
|
||||||
|
libcurl was built with support for IDNA, domain names with international
|
||||||
|
letters.
|
||||||
|
.RE
|
||||||
\fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl
|
\fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl
|
||||||
has no SSL support, this is NULL.
|
has no SSL support, this is NULL.
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<HTML>
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
<HEAD>
|
<html><head>
|
||||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<TITLE>Index to libcurl documentation</TITLE>
|
<title>Index to libcurl documentation</title>
|
||||||
</HEAD>
|
</head>
|
||||||
|
|
||||||
<BODY>
|
<body>
|
||||||
<H1 ALIGN="CENTER">Index to libcurl documentation</H1>
|
<h1 align="center">Index to libcurl documentation</h1>
|
||||||
|
|
||||||
<H2>Programs</H2>
|
<h2>Programs</h2>
|
||||||
<P><A HREF="../index.html">curl and tools</A>
|
<p><a href="../index.html">curl and tools</a>
|
||||||
|
|
||||||
<h2>Overviews</h2>
|
<h2>Overviews</h2>
|
||||||
<A HREF="libcurl.html">libcurl</A>
|
<A HREF="libcurl.html">libcurl</A>
|
||||||
@@ -25,10 +25,10 @@
|
|||||||
<br><a href="curl_easy_init.html">curl_easy_init</A>
|
<br><a href="curl_easy_init.html">curl_easy_init</A>
|
||||||
<br><a href="curl_easy_perform.html">curl_easy_perform</A>
|
<br><a href="curl_easy_perform.html">curl_easy_perform</A>
|
||||||
<br><a href="curl_easy_setopt.html">curl_easy_setopt</A>
|
<br><a href="curl_easy_setopt.html">curl_easy_setopt</A>
|
||||||
|
<br><a href="curl_easy_strerror.html">curl_easy_strerror</A>
|
||||||
<br><a href="curl_escape.html">curl_escape</A>
|
<br><a href="curl_escape.html">curl_escape</A>
|
||||||
<br><a href="curl_formadd.html">curl_formadd</A>
|
<br><a href="curl_formadd.html">curl_formadd</A>
|
||||||
<br><a href="curl_formfree.html">curl_formfree</A>
|
<br><a href="curl_formfree.html">curl_formfree</A>
|
||||||
<br><a href="curl_formparse.html">curl_formparse</A>
|
|
||||||
<br><a href="curl_free.html">curl_free</A>
|
<br><a href="curl_free.html">curl_free</A>
|
||||||
<br><a href="curl_getdate.html">curl_getdate</A>
|
<br><a href="curl_getdate.html">curl_getdate</A>
|
||||||
<br><a href="curl_getenv.html">curl_getenv</A>
|
<br><a href="curl_getenv.html">curl_getenv</A>
|
||||||
@@ -42,16 +42,16 @@
|
|||||||
<br><a href="curl_multi_init.html">curl_multi_init</a>
|
<br><a href="curl_multi_init.html">curl_multi_init</a>
|
||||||
<br><a href="curl_multi_perform.html">curl_multi_perform</a>
|
<br><a href="curl_multi_perform.html">curl_multi_perform</a>
|
||||||
<br><a href="curl_multi_remove_handle.html">curl_multi_remove_handle</a>
|
<br><a href="curl_multi_remove_handle.html">curl_multi_remove_handle</a>
|
||||||
|
<br><a href="curl_multi_strerror.html">curl_multi_strerror.html</a>
|
||||||
<br><a href="curl_share_cleanup.html">curl_share_cleanup</A>
|
<br><a href="curl_share_cleanup.html">curl_share_cleanup</A>
|
||||||
<br><a href="curl_share_init.html">curl_share_init</A>
|
<br><a href="curl_share_init.html">curl_share_init</A>
|
||||||
<br><a href="curl_share_setopt.html">curl_share_setopt</A>
|
<br><a href="curl_share_setopt.html">curl_share_setopt</A>
|
||||||
|
<br><a href="curl_share_strerror.html">curl_share_strerror.html</a>
|
||||||
<br><a href="curl_slist_append.html">curl_slist_append</A>
|
<br><a href="curl_slist_append.html">curl_slist_append</A>
|
||||||
<br><a href="curl_slist_free_all.html">curl_slist_free_all</A>
|
<br><a href="curl_slist_free_all.html">curl_slist_free_all</A>
|
||||||
<br><a href="curl_strequal.html">curl_strequal</A>
|
<br><a href="curl_strequal.html">curl_strequal and curl_strnequal</A>
|
||||||
<br><a href="curl_strnequal.html">curl_strnequal</A>
|
|
||||||
<br><a href="curl_unescape.html">curl_unescape</A>
|
<br><a href="curl_unescape.html">curl_unescape</A>
|
||||||
<br><a href="curl_version.html">curl_version</A>
|
<br><a href="curl_version.html">curl_version</A>
|
||||||
<br><a href="curl_version_info.html">curl_version_info</A>
|
<br><a href="curl_version_info.html">curl_version_info</A>
|
||||||
|
|
||||||
</BODY>
|
</body></html>
|
||||||
</HTML>
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
libcurl-easy \- easy interface overview
|
libcurl-easy \- easy interface overview
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
When using libcurl's "easy" interface you init your session and get a handle
|
When using libcurl's "easy" interface you init your session and get a handle
|
||||||
(often referred to as an "easy handle" in various docs and sources), which you
|
(often referred to as an "easy handle"), which you use as input to the easy
|
||||||
use as input to the easy interface functions you use. Use
|
interface functions you use. Use \fIcurl_easy_init(3)\fP to get the handle.
|
||||||
\fIcurl_easy_init(3)\fP to get the handle.
|
|
||||||
|
|
||||||
You continue by setting all the options you want in the upcoming transfer, the
|
You continue by setting all the options you want in the upcoming transfer, the
|
||||||
most important among them is the URL itself (you can't transfer anything
|
most important among them is the URL itself (you can't transfer anything
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH libcurl-errors 3 "8 Mar 2004" "libcurl 7.11.0" "libcurl errors"
|
.TH libcurl-errors 3 "27 Apr 2004" "libcurl 7.12" "libcurl errors"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
libcurl-errors \- error codes in libcurl
|
libcurl-errors \- error codes in libcurl
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -10,9 +10,11 @@ This man page includes most, if not all, available error codes in libcurl.
|
|||||||
Why they occur and possibly what you can do to fix the problem.
|
Why they occur and possibly what you can do to fix the problem.
|
||||||
.SH "CURLcode"
|
.SH "CURLcode"
|
||||||
Almost all "easy" interface functions return a CURLcode error code. No matter
|
Almost all "easy" interface functions return a CURLcode error code. No matter
|
||||||
what, using \fICURLOPT_ERRORBUFFER\fP is a good idea as it will give you a
|
what, using the \fIcurl_easy_setopt(3)\fP option \fICURLOPT_ERRORBUFFER\fP is
|
||||||
human readable error string that may offer more details about the error cause
|
a good idea as it will give you a human readable error string that may offer
|
||||||
than just the error code does.
|
more details about the error cause than just the error code
|
||||||
|
does. \fIcurl_easy_strerror(3)\fP can be called to get an error string from a
|
||||||
|
given CURLcode number.
|
||||||
|
|
||||||
CURLcode is one of the following:
|
CURLcode is one of the following:
|
||||||
.IP "CURLE_OK (0)"
|
.IP "CURLE_OK (0)"
|
||||||
@@ -168,8 +170,8 @@ Failed setting the selected SSL crypto engine as default!
|
|||||||
Failed sending network data.
|
Failed sending network data.
|
||||||
.IP "CURLE_RECV_ERROR (56)"
|
.IP "CURLE_RECV_ERROR (56)"
|
||||||
Failure with receiving network data.
|
Failure with receiving network data.
|
||||||
.IP "CURLE_RECV_ERROR (57)"
|
.IP "CURLE_SHARE_IN_USE (57)"
|
||||||
Failure with receiving network data.
|
Share is in use
|
||||||
.IP "CURLE_SSL_CERTPROBLEM (58)"
|
.IP "CURLE_SSL_CERTPROBLEM (58)"
|
||||||
problem with the local certificate
|
problem with the local certificate
|
||||||
.IP "CURLE_SSL_CIPHER (59)"
|
.IP "CURLE_SSL_CIPHER (59)"
|
||||||
@@ -186,7 +188,8 @@ Maximum file size exceeded
|
|||||||
Requested FTP SSL level failed
|
Requested FTP SSL level failed
|
||||||
.SH "CURLMcode"
|
.SH "CURLMcode"
|
||||||
This is the generic return code used by functions in the libcurl multi
|
This is the generic return code used by functions in the libcurl multi
|
||||||
interface.
|
interface. Also consider \fIcurl_multi_strerror(3)\fI.
|
||||||
|
|
||||||
.IP "CURLM_CALL_MULTI_PERFORM (-1)"
|
.IP "CURLM_CALL_MULTI_PERFORM (-1)"
|
||||||
This is not really an error. It means you should call
|
This is not really an error. It means you should call
|
||||||
\fIcurl_multi_perform(3)\fP again without doing select() or similar in between.
|
\fIcurl_multi_perform(3)\fP again without doing select() or similar in between.
|
||||||
@@ -201,8 +204,8 @@ You are doomed.
|
|||||||
.IP "CURLM_INTERNAL_ERROR (4)"
|
.IP "CURLM_INTERNAL_ERROR (4)"
|
||||||
This can only be returned if libcurl bugs. Please report it to us!
|
This can only be returned if libcurl bugs. Please report it to us!
|
||||||
.SH "CURLSHcode"
|
.SH "CURLSHcode"
|
||||||
The "share" interface will return a CURLSHcode to indicate when an
|
The "share" interface will return a CURLSHcode to indicate when an error has
|
||||||
error has occurred.
|
occurred. Also consider \fIcurl_share_strerror(3)\fI.
|
||||||
|
|
||||||
CURLSHcode is one of the following:
|
CURLSHcode is one of the following:
|
||||||
.IP "CURLSHE_OK (0)"
|
.IP "CURLSHE_OK (0)"
|
||||||
|
|||||||
@@ -33,45 +33,28 @@ The multi interface on the other hand is an asynchronous interface, that you
|
|||||||
call and that performs only a little piece of the transfer on each invoke. It
|
call and that performs only a little piece of the transfer on each invoke. It
|
||||||
is perfect if you want to do things while the transfer is in progress, or
|
is perfect if you want to do things while the transfer is in progress, or
|
||||||
similar. The multi interface allows you to select() on libcurl action, and
|
similar. The multi interface allows you to select() on libcurl action, and
|
||||||
even to easily download multiple files simultaneously using a single thread.
|
even to easily download multiple files simultaneously using a single thread. See further deails in the \fIlibcurl-multi(3)\fP man page.
|
||||||
|
|
||||||
You can have multiple easy handles share certain data, even if they are used
|
You can have multiple easy handles share certain data, even if they are used
|
||||||
in different threads. This magic is setup using the share interface, as
|
in different threads. This magic is setup using the share interface, as
|
||||||
described in the \fIlibcurl-share(3)\fP man page.
|
described in the \fIlibcurl-share(3)\fP man page.
|
||||||
|
|
||||||
There is also a series of other helpful functions to use. They are:
|
There is also a series of other helpful functions to use, including these:
|
||||||
|
|
||||||
.RS
|
.RS
|
||||||
.TP 10
|
.IP curl_version_info()
|
||||||
.B curl_version()
|
gets detailed libcurl (and other used libraries) version info
|
||||||
displays the libcurl version
|
.IP curl_getdate()
|
||||||
.TP
|
|
||||||
.B curl_getdate()
|
|
||||||
converts a date string to time_t
|
converts a date string to time_t
|
||||||
.TP
|
.IP curl_easy_getinfo()
|
||||||
.B curl_getenv()
|
|
||||||
portable environment variable reader
|
|
||||||
.TP
|
|
||||||
.B curl_easy_getinfo()
|
|
||||||
get information about a performed transfer
|
get information about a performed transfer
|
||||||
.TP
|
.IP curl_formadd()
|
||||||
.B curl_formadd()
|
|
||||||
helps building an HTTP form POST
|
helps building an HTTP form POST
|
||||||
.TP
|
.IP curl_formfree()
|
||||||
.B curl_formfree()
|
|
||||||
free a list built with \fIcurl_formadd(3)\fP
|
free a list built with \fIcurl_formadd(3)\fP
|
||||||
.TP
|
.IP curl_slist_append()
|
||||||
.B curl_slist_append()
|
|
||||||
builds a linked list
|
builds a linked list
|
||||||
.TP
|
.IP curl_slist_free_all()
|
||||||
.B curl_slist_free_all()
|
|
||||||
frees a whole curl_slist
|
frees a whole curl_slist
|
||||||
.TP
|
|
||||||
.B curl_mprintf()
|
|
||||||
portable printf() functions
|
|
||||||
.TP
|
|
||||||
.B curl_strequal()
|
|
||||||
portable case insensitive string comparisons
|
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.SH "LINKING WITH LIBCURL"
|
.SH "LINKING WITH LIBCURL"
|
||||||
@@ -82,13 +65,17 @@ curl-config is added to make it easier for applications to link with libcurl
|
|||||||
and developers to learn about libcurl and how to use it.
|
and developers to learn about libcurl and how to use it.
|
||||||
|
|
||||||
Run 'curl-config --libs' to get the (additional) linker options you need to
|
Run 'curl-config --libs' to get the (additional) linker options you need to
|
||||||
link with the particular version of libcurl you've installed.
|
link with the particular version of libcurl you've installed. See the
|
||||||
|
\fIcurl-config(1)\fP man page for further details.
|
||||||
|
|
||||||
|
Unix-like operating system that ship libcurl as part of their distributions
|
||||||
|
often don't provide the curl-config tool, but simply install the library and
|
||||||
|
headers in the common path for this purpose.
|
||||||
|
|
||||||
For details, see the curl-config.1 man page.
|
|
||||||
.SH "LIBCURL SYMBOL NAMES"
|
.SH "LIBCURL SYMBOL NAMES"
|
||||||
All public functions in the libcurl interface are prefixed with 'curl_' (with
|
All public functions in the libcurl interface are prefixed with 'curl_' (with
|
||||||
a lowercase c). You can find other functions in the library source code, but
|
a lowercase c). You can find other functions in the library source code, but
|
||||||
other prefixes indicate the functions are private and may change without
|
other prefixes indicate that the functions are private and may change without
|
||||||
further notice in the next release.
|
further notice in the next release.
|
||||||
|
|
||||||
Only use documented functions and functionality!
|
Only use documented functions and functionality!
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef __CURL_CURL_H
|
#ifndef __CURL_CURL_H
|
||||||
#define __CURL_CURL_H
|
#define __CURL_CURL_H
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
# include <time.h>
|
# include <time.h>
|
||||||
#endif /* defined (vms) */
|
#endif /* defined (vms) */
|
||||||
|
|
||||||
#include "types.h"
|
typedef void CURL;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -154,6 +154,18 @@ typedef int (*curl_passwd_callback)(void *clientp,
|
|||||||
char *buffer,
|
char *buffer,
|
||||||
int buflen);
|
int buflen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following typedef's are signatures of malloc, free, realloc, strdup and
|
||||||
|
* calloc respectively. Function pointers of these types can be passed to the
|
||||||
|
* curl_global_init_mem() function to set user defined memory management
|
||||||
|
* callback routines.
|
||||||
|
*/
|
||||||
|
typedef void *(*curl_malloc_callback)(size_t size);
|
||||||
|
typedef void (*curl_free_callback)(void *ptr);
|
||||||
|
typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
|
||||||
|
typedef char *(*curl_strdup_callback)(const char *str);
|
||||||
|
typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
|
||||||
|
|
||||||
/* the kind of data that is passed to information_callback*/
|
/* the kind of data that is passed to information_callback*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CURLINFO_TEXT = 0,
|
CURLINFO_TEXT = 0,
|
||||||
@@ -170,7 +182,7 @@ typedef int (*curl_debug_callback)
|
|||||||
char *data, /* points to the data */
|
char *data, /* points to the data */
|
||||||
size_t size, /* size of the data pointed to */
|
size_t size, /* size of the data pointed to */
|
||||||
void *userptr); /* whatever the user please */
|
void *userptr); /* whatever the user please */
|
||||||
|
|
||||||
/* All possible error codes from all sorts of curl functions. Future versions
|
/* All possible error codes from all sorts of curl functions. Future versions
|
||||||
may return other values, stay prepared.
|
may return other values, stay prepared.
|
||||||
|
|
||||||
@@ -183,7 +195,7 @@ typedef enum {
|
|||||||
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
|
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
|
||||||
CURLE_FAILED_INIT, /* 2 */
|
CURLE_FAILED_INIT, /* 2 */
|
||||||
CURLE_URL_MALFORMAT, /* 3 */
|
CURLE_URL_MALFORMAT, /* 3 */
|
||||||
CURLE_URL_MALFORMAT_USER, /* 4 */
|
CURLE_URL_MALFORMAT_USER, /* 4 (NOT USED) */
|
||||||
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
|
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
|
||||||
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
||||||
CURLE_COULDNT_CONNECT, /* 7 */
|
CURLE_COULDNT_CONNECT, /* 7 */
|
||||||
@@ -203,7 +215,7 @@ typedef enum {
|
|||||||
CURLE_FTP_QUOTE_ERROR, /* 21 */
|
CURLE_FTP_QUOTE_ERROR, /* 21 */
|
||||||
CURLE_HTTP_RETURNED_ERROR, /* 22 */
|
CURLE_HTTP_RETURNED_ERROR, /* 22 */
|
||||||
CURLE_WRITE_ERROR, /* 23 */
|
CURLE_WRITE_ERROR, /* 23 */
|
||||||
CURLE_MALFORMAT_USER, /* 24 - user name is illegally specified */
|
CURLE_MALFORMAT_USER, /* 24 - NOT USED */
|
||||||
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
|
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
|
||||||
CURLE_READ_ERROR, /* 26 - could open/read from file */
|
CURLE_READ_ERROR, /* 26 - could open/read from file */
|
||||||
CURLE_OUT_OF_MEMORY, /* 27 */
|
CURLE_OUT_OF_MEMORY, /* 27 */
|
||||||
@@ -223,13 +235,13 @@ typedef enum {
|
|||||||
CURLE_FUNCTION_NOT_FOUND, /* 41 */
|
CURLE_FUNCTION_NOT_FOUND, /* 41 */
|
||||||
CURLE_ABORTED_BY_CALLBACK, /* 42 */
|
CURLE_ABORTED_BY_CALLBACK, /* 42 */
|
||||||
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
|
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
|
||||||
CURLE_BAD_CALLING_ORDER, /* 44 */
|
CURLE_BAD_CALLING_ORDER, /* 44 - NOT USED */
|
||||||
CURLE_HTTP_PORT_FAILED, /* 45 - HTTP Interface operation failed */
|
CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
|
||||||
CURLE_BAD_PASSWORD_ENTERED, /* 46 - my_getpass() returns fail */
|
CURLE_BAD_PASSWORD_ENTERED, /* 46 - NOT USED */
|
||||||
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
|
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
|
||||||
CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
|
CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
|
||||||
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
|
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
|
||||||
CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */
|
CURLE_OBSOLETE, /* 50 - NOT USED */
|
||||||
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_NOTFOUND, /* 53 - SSL crypto engine not found */
|
||||||
@@ -244,7 +256,7 @@ typedef enum {
|
|||||||
CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */
|
CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */
|
||||||
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
|
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
|
||||||
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
|
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
|
||||||
CURLE_FTP_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
|
CURLE_FTP_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
|
||||||
|
|
||||||
CURL_LAST /* never use! */
|
CURL_LAST /* never use! */
|
||||||
} CURLcode;
|
} CURLcode;
|
||||||
@@ -256,7 +268,10 @@ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
|
|||||||
|
|
||||||
/* Make a spelling correction for the operation timed-out define */
|
/* Make a spelling correction for the operation timed-out define */
|
||||||
#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
|
#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
|
||||||
|
|
||||||
|
/* backwards compatibility with older names */
|
||||||
#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
|
#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
|
||||||
|
#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CURLPROXY_HTTP = 0,
|
CURLPROXY_HTTP = 0,
|
||||||
@@ -349,7 +364,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* Name of proxy to use. */
|
/* Name of proxy to use. */
|
||||||
CINIT(PROXY, OBJECTPOINT, 4),
|
CINIT(PROXY, OBJECTPOINT, 4),
|
||||||
|
|
||||||
/* "name:password" to use when fetching. */
|
/* "name:password" to use when fetching. */
|
||||||
CINIT(USERPWD, OBJECTPOINT, 5),
|
CINIT(USERPWD, OBJECTPOINT, 5),
|
||||||
|
|
||||||
@@ -406,7 +421,7 @@ typedef enum {
|
|||||||
/* If the download receives less than "low speed limit" bytes/second
|
/* If the download receives less than "low speed limit" bytes/second
|
||||||
* during "low speed time" seconds, the operations is aborted.
|
* during "low speed time" seconds, the operations is aborted.
|
||||||
* You could i.e if you have a pretty high speed connection, abort if
|
* You could i.e if you have a pretty high speed connection, abort if
|
||||||
* it is less than 2000 bytes/sec during 20 seconds.
|
* it is less than 2000 bytes/sec during 20 seconds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Set the "low speed limit" */
|
/* Set the "low speed limit" */
|
||||||
@@ -439,7 +454,7 @@ typedef enum {
|
|||||||
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
|
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
|
||||||
/* password for the SSL private key */
|
/* password for the SSL private key */
|
||||||
CINIT(SSLKEYPASSWD, OBJECTPOINT, 26),
|
CINIT(SSLKEYPASSWD, OBJECTPOINT, 26),
|
||||||
|
|
||||||
/* send TYPE parameter? */
|
/* send TYPE parameter? */
|
||||||
CINIT(CRLF, LONG, 27),
|
CINIT(CRLF, LONG, 27),
|
||||||
|
|
||||||
@@ -538,14 +553,14 @@ typedef enum {
|
|||||||
|
|
||||||
/* Set if we should verify the peer in ssl handshake, set 1 to verify. */
|
/* Set if we should verify the peer in ssl handshake, set 1 to verify. */
|
||||||
CINIT(SSL_VERIFYPEER, LONG, 64),
|
CINIT(SSL_VERIFYPEER, LONG, 64),
|
||||||
|
|
||||||
/* The CApath or CAfile used to validate the peer certificate
|
/* The CApath or CAfile used to validate the peer certificate
|
||||||
this option is used only if SSL_VERIFYPEER is true */
|
this option is used only if SSL_VERIFYPEER is true */
|
||||||
CINIT(CAINFO, OBJECTPOINT, 65),
|
CINIT(CAINFO, OBJECTPOINT, 65),
|
||||||
|
|
||||||
/* 66 = OBSOLETE */
|
/* 66 = OBSOLETE */
|
||||||
/* 67 = OBSOLETE */
|
/* 67 = OBSOLETE */
|
||||||
|
|
||||||
/* Maximum number of http redirects to follow */
|
/* Maximum number of http redirects to follow */
|
||||||
CINIT(MAXREDIRS, LONG, 68),
|
CINIT(MAXREDIRS, LONG, 68),
|
||||||
|
|
||||||
@@ -614,7 +629,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* Specificly switch on or off the FTP engine's use of the EPSV command. By
|
/* 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
|
default, that one will always be attempted before the more traditional
|
||||||
PASV command. */
|
PASV command. */
|
||||||
CINIT(FTP_USE_EPSV, LONG, 85),
|
CINIT(FTP_USE_EPSV, LONG, 85),
|
||||||
|
|
||||||
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
|
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
|
||||||
@@ -663,7 +678,7 @@ typedef enum {
|
|||||||
timeouts. This option is useful for multi-threaded applications.
|
timeouts. This option is useful for multi-threaded applications.
|
||||||
See libcurl-the-guide for more background information. */
|
See libcurl-the-guide for more background information. */
|
||||||
CINIT(NOSIGNAL, LONG, 99),
|
CINIT(NOSIGNAL, LONG, 99),
|
||||||
|
|
||||||
/* Provide a CURLShare for mutexing non-ts data */
|
/* Provide a CURLShare for mutexing non-ts data */
|
||||||
CINIT(SHARE, OBJECTPOINT, 100),
|
CINIT(SHARE, OBJECTPOINT, 100),
|
||||||
|
|
||||||
@@ -674,7 +689,7 @@ typedef enum {
|
|||||||
/* Set the Accept-Encoding string. Use this to tell a server you would like
|
/* Set the Accept-Encoding string. Use this to tell a server you would like
|
||||||
the response to be compressed. */
|
the response to be compressed. */
|
||||||
CINIT(ENCODING, OBJECTPOINT, 102),
|
CINIT(ENCODING, OBJECTPOINT, 102),
|
||||||
|
|
||||||
/* Set pointer to private data */
|
/* Set pointer to private data */
|
||||||
CINIT(PRIVATE, OBJECTPOINT, 103),
|
CINIT(PRIVATE, OBJECTPOINT, 103),
|
||||||
|
|
||||||
@@ -688,7 +703,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* Specificly switch on or off the FTP engine's use of the EPRT command ( it
|
/* Specificly switch on or off the FTP engine's use of the EPRT command ( it
|
||||||
also disables the LPRT attempt). By default, those ones will always be
|
also disables the LPRT attempt). By default, those ones will always be
|
||||||
attempted before the good old traditional PORT command. */
|
attempted before the good old traditional PORT command. */
|
||||||
CINIT(FTP_USE_EPRT, LONG, 106),
|
CINIT(FTP_USE_EPRT, LONG, 106),
|
||||||
|
|
||||||
/* Set this to a bitmask value to enable the particular authentications
|
/* Set this to a bitmask value to enable the particular authentications
|
||||||
@@ -713,7 +728,7 @@ typedef enum {
|
|||||||
Note that setting multiple bits may cause extra network round-trips. */
|
Note that setting multiple bits may cause extra network round-trips. */
|
||||||
CINIT(PROXYAUTH, LONG, 111),
|
CINIT(PROXYAUTH, LONG, 111),
|
||||||
|
|
||||||
/* FTP option that changes the timeout, in seconds, associated with
|
/* FTP option that changes the timeout, in seconds, associated with
|
||||||
getting a response. This is different from transfer timeout time and
|
getting a response. This is different from transfer timeout time and
|
||||||
essentially places a demand on the FTP server to acknowledge commands
|
essentially places a demand on the FTP server to acknowledge commands
|
||||||
in a timely manner. */
|
in a timely manner. */
|
||||||
@@ -778,7 +793,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* three convenient "aliases" that follow the name scheme better */
|
/* three convenient "aliases" that follow the name scheme better */
|
||||||
#define CURLOPT_WRITEDATA CURLOPT_FILE
|
#define CURLOPT_WRITEDATA CURLOPT_FILE
|
||||||
#define CURLOPT_READDATA CURLOPT_INFILE
|
#define CURLOPT_READDATA CURLOPT_INFILE
|
||||||
#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
|
#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
|
||||||
|
|
||||||
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
||||||
@@ -792,7 +807,6 @@ typedef enum {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
/* This is set if CURL_NO_OLDIES is defined at compile-time */
|
/* This is set if CURL_NO_OLDIES is defined at compile-time */
|
||||||
#define curl_formparse "curl_formparse is obsolete"
|
|
||||||
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
|
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -804,7 +818,7 @@ enum {
|
|||||||
for us! */
|
for us! */
|
||||||
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
|
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
|
||||||
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
||||||
|
|
||||||
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -845,23 +859,11 @@ typedef enum {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* These functions are in libcurl, they're here for portable reasons and they
|
/* curl_strequal() and curl_strnequal() are subject for removal in a future
|
||||||
are used by the 'curl' client. They really should be moved to some kind of
|
libcurl, see lib/README.curlx for details */
|
||||||
"portability library" since it has nothing to do with file transfers and
|
|
||||||
might be usable to other programs...
|
|
||||||
|
|
||||||
NOTE: they return TRUE if the strings match *case insensitively*.
|
|
||||||
*/
|
|
||||||
extern int (curl_strequal)(const char *s1, const char *s2);
|
extern int (curl_strequal)(const char *s1, const char *s2);
|
||||||
extern int (curl_strnequal)(const char *s1, const char *s2, size_t n);
|
extern int (curl_strnequal)(const char *s1, const char *s2, size_t n);
|
||||||
|
|
||||||
#ifdef CURL_OLDSTYLE
|
|
||||||
/* DEPRECATED function to build formdata. Stop using this, it will cease
|
|
||||||
to exist. */
|
|
||||||
int curl_formparse(char *, struct curl_httppost **,
|
|
||||||
struct curl_httppost **_post);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* name is uppercase CURLFORM_<name> */
|
/* name is uppercase CURLFORM_<name> */
|
||||||
#ifdef CFINIT
|
#ifdef CFINIT
|
||||||
#undef CFINIT
|
#undef CFINIT
|
||||||
@@ -876,7 +878,7 @@ int curl_formparse(char *, struct curl_httppost **,
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CFINIT(NOTHING), /********* the first one is unused ************/
|
CFINIT(NOTHING), /********* the first one is unused ************/
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
CFINIT(COPYNAME),
|
CFINIT(COPYNAME),
|
||||||
CFINIT(PTRNAME),
|
CFINIT(PTRNAME),
|
||||||
@@ -912,7 +914,7 @@ struct curl_forms {
|
|||||||
|
|
||||||
/* use this for multipart formpost building */
|
/* use this for multipart formpost building */
|
||||||
/* Returns code for curl_formadd()
|
/* Returns code for curl_formadd()
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* CURL_FORMADD_OK on success
|
* CURL_FORMADD_OK on success
|
||||||
* CURL_FORMADD_MEMORY if the FormInfo allocation fails
|
* CURL_FORMADD_MEMORY if the FormInfo allocation fails
|
||||||
@@ -967,7 +969,7 @@ void curl_formfree(struct curl_httppost *form);
|
|||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
*
|
*
|
||||||
* Returns a malloc()'ed string that MUST be curl_free()ed after usage is
|
* Returns a malloc()'ed string that MUST be curl_free()ed after usage is
|
||||||
* complete.
|
* complete. DEPRECATED - see lib/README.curlx
|
||||||
*/
|
*/
|
||||||
char *curl_getenv(const char *variable);
|
char *curl_getenv(const char *variable);
|
||||||
|
|
||||||
@@ -1022,6 +1024,26 @@ void curl_free(void *p);
|
|||||||
*/
|
*/
|
||||||
CURLcode curl_global_init(long flags);
|
CURLcode curl_global_init(long flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NAME curl_global_init_mem()
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
*
|
||||||
|
* curl_global_init() or curl_global_init_mem() should be invoked exactly once
|
||||||
|
* for each application that uses libcurl. This function can be used to
|
||||||
|
* initialize libcurl and set user defined memory management callback
|
||||||
|
* functions. Users can implement memory management routines to check for
|
||||||
|
* memory leaks, check for mis-use of the curl library etc. User registered
|
||||||
|
* callback routines with be invoked by this library instead of the system
|
||||||
|
* memory management routines like malloc, free etc.
|
||||||
|
*/
|
||||||
|
CURLcode curl_global_init_mem(long flags,
|
||||||
|
curl_malloc_callback m,
|
||||||
|
curl_free_callback f,
|
||||||
|
curl_realloc_callback r,
|
||||||
|
curl_strdup_callback s,
|
||||||
|
curl_calloc_callback c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME curl_global_cleanup()
|
* NAME curl_global_cleanup()
|
||||||
*
|
*
|
||||||
@@ -1118,7 +1140,7 @@ typedef enum {
|
|||||||
CURLCLOSEPOLICY_LEAST_TRAFFIC,
|
CURLCLOSEPOLICY_LEAST_TRAFFIC,
|
||||||
CURLCLOSEPOLICY_SLOWEST,
|
CURLCLOSEPOLICY_SLOWEST,
|
||||||
CURLCLOSEPOLICY_CALLBACK,
|
CURLCLOSEPOLICY_CALLBACK,
|
||||||
|
|
||||||
CURLCLOSEPOLICY_LAST /* last, never use this */
|
CURLCLOSEPOLICY_LAST /* last, never use this */
|
||||||
} curl_closepolicy;
|
} curl_closepolicy;
|
||||||
|
|
||||||
@@ -1140,7 +1162,7 @@ typedef enum {
|
|||||||
* the locking is just made to change the internal state of the share
|
* the locking is just made to change the internal state of the share
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
CURL_LOCK_DATA_SHARE,
|
CURL_LOCK_DATA_SHARE,
|
||||||
CURL_LOCK_DATA_COOKIE,
|
CURL_LOCK_DATA_COOKIE,
|
||||||
CURL_LOCK_DATA_DNS,
|
CURL_LOCK_DATA_DNS,
|
||||||
CURL_LOCK_DATA_SSL_SESSION,
|
CURL_LOCK_DATA_SSL_SESSION,
|
||||||
@@ -1171,6 +1193,7 @@ typedef enum {
|
|||||||
CURLSHE_BAD_OPTION, /* 1 */
|
CURLSHE_BAD_OPTION, /* 1 */
|
||||||
CURLSHE_IN_USE, /* 2 */
|
CURLSHE_IN_USE, /* 2 */
|
||||||
CURLSHE_INVALID, /* 3 */
|
CURLSHE_INVALID, /* 3 */
|
||||||
|
CURLSHE_NOMEM, /* out of memory */
|
||||||
CURLSHE_LAST /* never use */
|
CURLSHE_LAST /* never use */
|
||||||
} CURLSHcode;
|
} CURLSHcode;
|
||||||
|
|
||||||
@@ -1196,6 +1219,7 @@ CURLSHcode curl_share_cleanup(CURLSH *);
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
CURLVERSION_FIRST,
|
CURLVERSION_FIRST,
|
||||||
CURLVERSION_SECOND,
|
CURLVERSION_SECOND,
|
||||||
|
CURLVERSION_THIRD,
|
||||||
CURLVERSION_LAST /* never actually use this */
|
CURLVERSION_LAST /* never actually use this */
|
||||||
} CURLversion;
|
} CURLversion;
|
||||||
|
|
||||||
@@ -1204,7 +1228,7 @@ typedef enum {
|
|||||||
meant to be a built-in version number for what kind of struct the caller
|
meant to be a built-in version number for what kind of struct the caller
|
||||||
expects. If the struct ever changes, we redfine the NOW to another enum
|
expects. If the struct ever changes, we redfine the NOW to another enum
|
||||||
from above. */
|
from above. */
|
||||||
#define CURLVERSION_NOW CURLVERSION_SECOND
|
#define CURLVERSION_NOW CURLVERSION_THIRD
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CURLversion age; /* age of the returned struct */
|
CURLversion age; /* age of the returned struct */
|
||||||
@@ -1221,18 +1245,22 @@ typedef struct {
|
|||||||
/* The fields below this were added in CURLVERSION_SECOND */
|
/* The fields below this were added in CURLVERSION_SECOND */
|
||||||
const char *ares;
|
const char *ares;
|
||||||
int ares_num;
|
int ares_num;
|
||||||
|
|
||||||
|
/* This field was aded in CURLVERSION_THIRD */
|
||||||
|
const char *libidn;
|
||||||
} curl_version_info_data;
|
} curl_version_info_data;
|
||||||
|
|
||||||
#define CURL_VERSION_IPV6 (1<<0)
|
#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
|
||||||
#define CURL_VERSION_KERBEROS4 (1<<1)
|
#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */
|
||||||
#define CURL_VERSION_SSL (1<<2)
|
#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
|
||||||
#define CURL_VERSION_LIBZ (1<<3)
|
#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
|
||||||
#define CURL_VERSION_NTLM (1<<4)
|
#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
|
||||||
#define CURL_VERSION_GSSNEGOTIATE (1<<5)
|
#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */
|
||||||
#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
|
#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
|
||||||
#define CURL_VERSION_ASYNCHDNS (1<<7)
|
#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
|
||||||
#define CURL_VERSION_SPNEGO (1<<8)
|
#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */
|
||||||
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
|
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
|
||||||
|
#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME curl_version_info()
|
* NAME curl_version_info()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
/* This is the version number of the libcurl package from which this header
|
/* This is the version number of the libcurl package from which this header
|
||||||
file origins: */
|
file origins: */
|
||||||
#define LIBCURL_VERSION "7.11.2-CVS"
|
#define LIBCURL_VERSION "7.12.0-CVS"
|
||||||
|
|
||||||
/* This is the numeric version of the libcurl version number, meant for easier
|
/* This is the numeric version of the libcurl version number, meant for easier
|
||||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||||
@@ -44,12 +44,12 @@
|
|||||||
always a greater number in a more recent release. It makes comparisons with
|
always a greater number in a more recent release. It makes comparisons with
|
||||||
greater than and less than work.
|
greater than and less than work.
|
||||||
*/
|
*/
|
||||||
#define LIBCURL_VERSION_NUM 0x070b02
|
#define LIBCURL_VERSION_NUM 0x070c00
|
||||||
|
|
||||||
/* The numeric version number is also available "in parts" by using these
|
/* The numeric version number is also available "in parts" by using these
|
||||||
defines: */
|
defines: */
|
||||||
#define LIBCURL_VERSION_MAJOR 7
|
#define LIBCURL_VERSION_MAJOR 7
|
||||||
#define LIBCURL_VERSION_MINOR 11
|
#define LIBCURL_VERSION_MINOR 12
|
||||||
#define LIBCURL_VERSION_PATCH 2
|
#define LIBCURL_VERSION_PATCH 0
|
||||||
|
|
||||||
#endif /* __CURL_CURLVER_H */
|
#endif /* __CURL_CURLVER_H */
|
||||||
|
|||||||
@@ -1,28 +1 @@
|
|||||||
#ifndef __CURL_TYPES_H
|
/* not used */
|
||||||
#define __CURL_TYPES_H
|
|
||||||
/***************************************************************************
|
|
||||||
* _ _ ____ _
|
|
||||||
* Project ___| | | | _ \| |
|
|
||||||
* / __| | | | |_) | |
|
|
||||||
* | (__| |_| | _ <| |___
|
|
||||||
* \___|\___/|_| \_\_____|
|
|
||||||
*
|
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
||||||
*
|
|
||||||
* This software is licensed as described in the file COPYING, which
|
|
||||||
* you should have received as part of this distribution. The terms
|
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
|
||||||
*
|
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
||||||
* copies of the Software, and permit persons to whom the Software is
|
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
***************************************************************************/
|
|
||||||
typedef void CURL;
|
|
||||||
typedef void CURLconnect;
|
|
||||||
|
|
||||||
#endif /* __CURL_TYPES_H */
|
|
||||||
|
|||||||
@@ -22,13 +22,18 @@
|
|||||||
###########################################################################
|
###########################################################################
|
||||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||||
|
|
||||||
EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \
|
DSP = curllib.dsp
|
||||||
Makefile.vc6 Makefile.riscos libcurl.def curllib.dsp curllib.dsw \
|
|
||||||
config-vms.h config-win32.h config-riscos.h config-mac.h config.h.in \
|
EXTRA_DIST = getdate.y Makefile.b32 Makefile.b32.resp Makefile.m32 \
|
||||||
ca-bundle.crt README.encoding README.memoryleak README.ares README.curlx \
|
Makefile.vc6 Makefile.riscos libcurl.def $(DSP) curllib.dsw \
|
||||||
makefile.dj config.dj libcurl.framework.make libcurl.plist libcurl.rc \
|
config-vms.h config-win32.h config-riscos.h config-mac.h config.h.in \
|
||||||
config-amigaos.h amigaos.c amigaos.h makefile.amiga config-netware.h \
|
ca-bundle.crt README.encoding README.memoryleak README.ares \
|
||||||
Makefile.netware nwlib.c libcurl.imp
|
README.curlx makefile.dj config.dj libcurl.framework.make \
|
||||||
|
libcurl.plist libcurl.rc config-amigaos.h amigaos.c amigaos.h \
|
||||||
|
makefile.amiga config-netware.h Makefile.netware nwlib.c libcurl.imp \
|
||||||
|
msvcproj.head msvcproj.foot
|
||||||
|
|
||||||
|
CLEANFILES = $(DSP)
|
||||||
|
|
||||||
lib_LTLIBRARIES = libcurl.la
|
lib_LTLIBRARIES = libcurl.la
|
||||||
|
|
||||||
@@ -37,7 +42,7 @@ lib_LTLIBRARIES = libcurl.la
|
|||||||
# we use srcdir/lib for the lib-private header files
|
# we use srcdir/lib for the lib-private header files
|
||||||
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/lib -I$(top_srcdir)/lib
|
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/lib -I$(top_srcdir)/lib
|
||||||
|
|
||||||
VERSION=-version-info 2:2:0
|
VERSION=-version-info 3:0:0
|
||||||
|
|
||||||
# This flag accepts an argument of the form current[:revision[:age]]. So,
|
# This flag accepts an argument of the form current[:revision[:age]]. So,
|
||||||
# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
|
# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
|
||||||
@@ -80,22 +85,29 @@ endif
|
|||||||
|
|
||||||
libcurl_la_LDFLAGS = $(UNDEF) $(VERSION) $(MIMPURE)
|
libcurl_la_LDFLAGS = $(UNDEF) $(VERSION) $(MIMPURE)
|
||||||
|
|
||||||
libcurl_la_SOURCES = arpa_telnet.h file.c netrc.h timeval.c base64.c \
|
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||||
file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h \
|
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||||
progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h \
|
if2ip.h speedcheck.h urldata.h getdate.h ldap.h ssluse.h escape.h \
|
||||||
sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h \
|
telnet.h getinfo.h strequal.h security.h krb4.h memdebug.h \
|
||||||
getdate.c if2ip.h speedcheck.h urldata.h getdate.h ldap.c ssluse.c \
|
inet_ntoa_r.h http_chunks.h strtok.h connect.h llist.h hash.h \
|
||||||
version.c getenv.c ldap.h ssluse.h escape.c mprintf.c telnet.c \
|
content_encoding.h share.h md5.h http_digest.h http_negotiate.h \
|
||||||
escape.h netrc.c telnet.h getinfo.c getinfo.h transfer.c strequal.c \
|
http_ntlm.h ca-bundle.h inet_pton.h strtoofft.h strerror.h \
|
||||||
strequal.h easy.c security.h security.c krb4.c krb4.h memdebug.c \
|
inet_ntop.h curlx.h memory.h setup.h transfer.h
|
||||||
memdebug.h inet_ntoa_r.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 \
|
|
||||||
content_encoding.c content_encoding.h share.c share.h http_digest.c \
|
|
||||||
md5.c md5.h http_digest.h http_negotiate.c http_negotiate.h \
|
|
||||||
http_ntlm.c http_ntlm.h ca-bundle.h inet_pton.c inet_pton.h \
|
|
||||||
strtoofft.c strtoofft.h strerror.c strerror.h
|
|
||||||
|
|
||||||
noinst_HEADERS = setup.h transfer.h
|
CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||||
|
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
|
||||||
|
getdate.c ldap.c ssluse.c version.c getenv.c escape.c mprintf.c \
|
||||||
|
telnet.c netrc.c getinfo.c transfer.c strequal.c easy.c security.c \
|
||||||
|
krb4.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c \
|
||||||
|
multi.c content_encoding.c share.c http_digest.c md5.c \
|
||||||
|
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
|
||||||
|
hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \
|
||||||
|
inet_ntop.c
|
||||||
|
|
||||||
|
libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS)
|
||||||
|
|
||||||
|
WIN32SOURCES = $(CSOURCES)
|
||||||
|
WIN32HEADERS = $(HHEADERS) config-win32.h
|
||||||
|
|
||||||
BUILT_SOURCES = $(srcdir)/getdate.c $(top_builddir)/lib/ca-bundle.h
|
BUILT_SOURCES = $(srcdir)/getdate.c $(top_builddir)/lib/ca-bundle.h
|
||||||
|
|
||||||
@@ -127,3 +139,26 @@ install-data-hook:
|
|||||||
dist-hook:
|
dist-hook:
|
||||||
chmod 0644 $(distdir)/ca-bundle.h
|
chmod 0644 $(distdir)/ca-bundle.h
|
||||||
echo "/* ca bundle path set in here*/" > $(distdir)/ca-bundle.h
|
echo "/* ca bundle path set in here*/" > $(distdir)/ca-bundle.h
|
||||||
|
|
||||||
|
DSPOUT = | awk '{printf("%s\r\n", $$0)}' >> $(DSP)
|
||||||
|
|
||||||
|
$(DSP): msvcproj.head msvcproj.foot Makefile.am
|
||||||
|
echo "creating $(DSP)"
|
||||||
|
@(cp msvcproj.head $(DSP); \
|
||||||
|
echo "# Begin Group \"Source Files\"" $(DSPOUT); \
|
||||||
|
for file in $(WIN32SOURCES); do \
|
||||||
|
echo "# Begin Source File" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
echo "SOURCE=.\\"$$file $(DSPOUT); \
|
||||||
|
echo "# End Source File" $(DSPOUT); \
|
||||||
|
done; \
|
||||||
|
echo "# End Group" $(DSPOUT); \
|
||||||
|
echo "# Begin Group \"Header Files\"" $(DSPOUT); \
|
||||||
|
for file in $(WIN32HEADERS); do \
|
||||||
|
echo "# Begin Source File" $(DSPOUT); \
|
||||||
|
echo "" $(DSPOUT); \
|
||||||
|
echo "SOURCE=.\\"$$file $(DSPOUT); \
|
||||||
|
echo "# End Source File" $(DSPOUT); \
|
||||||
|
done; \
|
||||||
|
echo "# End Group" $(DSPOUT); \
|
||||||
|
cat msvcproj.foot $(DSPOUT) )
|
||||||
|
|||||||
@@ -21,16 +21,6 @@
|
|||||||
#
|
#
|
||||||
# $Id: Makefile.vc6,v 1.17 2004/01/13 08:57:01 bagder Exp $
|
# $Id: Makefile.vc6,v 1.17 2004/01/13 08:57:01 bagder Exp $
|
||||||
##############################################################
|
##############################################################
|
||||||
# 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
|
|
||||||
# 10.14.2003 Added a target release-libcurl-ssl-dll which
|
|
||||||
# is intended to allow static linking of libcurl with dynamic
|
|
||||||
# linking of openssl
|
|
||||||
##############################################################
|
|
||||||
|
|
||||||
LIB_NAME = libcurl
|
LIB_NAME = libcurl
|
||||||
LIB_NAME_DEBUG = libcurld
|
LIB_NAME_DEBUG = libcurld
|
||||||
@@ -42,6 +32,10 @@ OPENSSL_PATH = ../../openssl-0.9.7a
|
|||||||
ZLIB_PATH = ../../zlib-1.1.4
|
ZLIB_PATH = ../../zlib-1.1.4
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
# Use the high resolution time by default. Comment this out to use low
|
||||||
|
# resolution time and not require winmm.lib
|
||||||
|
USEMM_LIBS = YES
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
## Nothing more to do below this line!
|
## Nothing more to do below this line!
|
||||||
|
|
||||||
@@ -49,12 +43,17 @@ CCNODBG = cl.exe /MD /O2 /D "NDEBUG"
|
|||||||
CCDEBUG = cl.exe /MDd /Od /Gm /Zi /D "_DEBUG" /GZ
|
CCDEBUG = cl.exe /MDd /Od /Gm /Zi /D "_DEBUG" /GZ
|
||||||
CFLAGSSSL = /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
|
CFLAGSSSL = /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
|
||||||
CFLAGSZLIB = /D "HAVE_ZLIB_H" /D "HAVE_ZLIB" /D "HAVE_LIBZ" /I "$(ZLIB_PATH)"
|
CFLAGSZLIB = /D "HAVE_ZLIB_H" /D "HAVE_ZLIB" /D "HAVE_LIBZ" /I "$(ZLIB_PATH)"
|
||||||
CFLAGS = /I "." /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS"
|
CFLAGS = /I "." /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
|
LNKDLL = link.exe /DLL /def:libcurl.def
|
||||||
LNKLIB = link.exe /lib
|
LNKLIB = link.exe /lib
|
||||||
LFLAGS = /nologo
|
LFLAGS = /nologo
|
||||||
SSLLIBS = libeay32.lib ssleay32.lib
|
SSLLIBS = libeay32.lib ssleay32.lib
|
||||||
|
!IFDEF USEMM_LIBS
|
||||||
|
WINLIBS = wsock32.lib winmm.lib
|
||||||
|
!ELSE
|
||||||
|
WINLIBS = wsock32.lib
|
||||||
|
CFLAGS = $(CFLAGS) /D "WITHOUT_MM_LIB"
|
||||||
|
!ENDIF
|
||||||
# RSAglue.lib was formerly needed in the SSLLIBS
|
# RSAglue.lib was formerly needed in the SSLLIBS
|
||||||
CFGSET = FALSE
|
CFGSET = FALSE
|
||||||
|
|
||||||
@@ -69,6 +68,18 @@ CC = $(CCNODBG)
|
|||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
######################
|
||||||
|
# release-zlib
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "release-zlib"
|
||||||
|
TARGET =$(LIB_NAME).lib
|
||||||
|
DIROBJ =.\$(CFG)
|
||||||
|
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
|
||||||
|
LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(TARGET)
|
||||||
|
CC = $(CCNODBG) $(CFLAGSZLIB)
|
||||||
|
CFGSET = TRUE
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# release-dll
|
# release-dll
|
||||||
|
|
||||||
@@ -100,7 +111,7 @@ CFGSET = TRUE
|
|||||||
TARGET =$(LIB_NAME).dll
|
TARGET =$(LIB_NAME).dll
|
||||||
DIROBJ =.\$(CFG)
|
DIROBJ =.\$(CFG)
|
||||||
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"
|
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"
|
||||||
LNK = $(LNKDLL) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
|
LNK = $(LNKDLL) $(SSLLIBS) $(WINLIBS) $(LFLAGSSSL) /out:$(TARGET) /IMPLIB:"$(LIB_NAME).lib"
|
||||||
CC = $(CCNODBG) $(CFLAGSSSL)
|
CC = $(CCNODBG) $(CFLAGSSSL)
|
||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
RESOURCE = $(DIROBJ)\libcurl.res
|
RESOURCE = $(DIROBJ)\libcurl.res
|
||||||
@@ -108,7 +119,6 @@ RESOURCE = $(DIROBJ)\libcurl.res
|
|||||||
|
|
||||||
######################
|
######################
|
||||||
# release-ssl-zlib
|
# release-ssl-zlib
|
||||||
|
|
||||||
!IF "$(CFG)" == "release-ssl-zlib"
|
!IF "$(CFG)" == "release-ssl-zlib"
|
||||||
TARGET =$(LIB_NAME).lib
|
TARGET =$(LIB_NAME).lib
|
||||||
DIROBJ =.\$(CFG)
|
DIROBJ =.\$(CFG)
|
||||||
@@ -125,7 +135,7 @@ CFGSET = TRUE
|
|||||||
TARGET =$(LIB_NAME).lib
|
TARGET =$(LIB_NAME).lib
|
||||||
DIROBJ =.\$(CFG)
|
DIROBJ =.\$(CFG)
|
||||||
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"
|
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)/out32dll"
|
||||||
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(TARGET)
|
LNK = $(LNKLIB) $(SSLLIBS) $(LFLAGSSSL) /out:$(TARGET)
|
||||||
CC = $(CCNODBG) $(CFLAGSSSL)
|
CC = $(CCNODBG) $(CFLAGSSSL)
|
||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
RESOURCE = $(DIROBJ)\libcurl.res
|
RESOURCE = $(DIROBJ)\libcurl.res
|
||||||
@@ -166,6 +176,17 @@ CC = $(CCDEBUG) $(CFLAGSSSL)
|
|||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
######################
|
||||||
|
# debug-zlib
|
||||||
|
!IF "$(CFG)" == "debug-zlib"
|
||||||
|
TARGET = $(LIB_NAME_DEBUG).lib
|
||||||
|
DIROBJ =.\$(CFG)
|
||||||
|
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
|
||||||
|
LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(TARGET)
|
||||||
|
CC = $(CCDEBUG) $(CFLAGSZLIB)
|
||||||
|
CFGSET = TRUE
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# debug-ssl-dll
|
# debug-ssl-dll
|
||||||
|
|
||||||
@@ -187,12 +208,14 @@ RESOURCE = $(DIROBJ)\libcurl.res
|
|||||||
!MESSAGE where <config> is one of:
|
!MESSAGE where <config> is one of:
|
||||||
!MESSAGE release - release static library
|
!MESSAGE release - release static library
|
||||||
!MESSAGE release-dll - release dll
|
!MESSAGE release-dll - release dll
|
||||||
|
!MESSAGE release-zlib - release static library with zlib
|
||||||
!MESSAGE release-ssl - release static library with ssl
|
!MESSAGE release-ssl - release static library with ssl
|
||||||
!MESSAGE release-ssl-zlib - release static library with ssl and zlib
|
!MESSAGE release-ssl-zlib - release static library with ssl and zlib
|
||||||
!MESSAGE release-ssl-dll - release dll library with ssl
|
!MESSAGE release-ssl-dll - release dll library with ssl
|
||||||
!MESSAGE release-libcurl-ssl-dll - static libcurl with shared ssl
|
!MESSAGE release-libcurl-ssl-dll - static libcurl with shared ssl
|
||||||
!MESSAGE debug - debug static library
|
!MESSAGE debug - debug static library
|
||||||
!MESSAGE debug-dll - debug dll
|
!MESSAGE debug-dll - debug dll
|
||||||
|
!MESSAGE debug-zlib - debug static library with zlib
|
||||||
!MESSAGE debug-ssl - debug static library with ssl
|
!MESSAGE debug-ssl - debug static library with ssl
|
||||||
!MESSAGE debug-ssl-dll - debug dll library with ssl
|
!MESSAGE debug-ssl-dll - debug dll library with ssl
|
||||||
!MESSAGE <target> can be left blank in which case all is assumed
|
!MESSAGE <target> can be left blank in which case all is assumed
|
||||||
@@ -217,6 +240,13 @@ X_OBJS= \
|
|||||||
$(DIROBJ)\getenv.obj \
|
$(DIROBJ)\getenv.obj \
|
||||||
$(DIROBJ)\inet_pton.obj \
|
$(DIROBJ)\inet_pton.obj \
|
||||||
$(DIROBJ)\hostip.obj \
|
$(DIROBJ)\hostip.obj \
|
||||||
|
$(DIROBJ)\hostasyn.obj \
|
||||||
|
$(DIROBJ)\hostsyn.obj \
|
||||||
|
$(DIROBJ)\hostares.obj \
|
||||||
|
$(DIROBJ)\hostthre.obj \
|
||||||
|
$(DIROBJ)\hostip4.obj \
|
||||||
|
$(DIROBJ)\hostip6.obj \
|
||||||
|
$(DIROBJ)\inet_ntop.obj \
|
||||||
$(DIROBJ)\if2ip.obj \
|
$(DIROBJ)\if2ip.obj \
|
||||||
$(DIROBJ)\mprintf.obj \
|
$(DIROBJ)\mprintf.obj \
|
||||||
$(DIROBJ)\netrc.obj \
|
$(DIROBJ)\netrc.obj \
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ part of the official libcurl API, but the source files might be useful for
|
|||||||
others so apps can optionally compile/build with these sources to gain
|
others so apps can optionally compile/build with these sources to gain
|
||||||
additional functions.
|
additional functions.
|
||||||
|
|
||||||
|
We provide them through a single header file for easy access for apps:
|
||||||
strtoofft.[ch]
|
"curlx.h"
|
||||||
==============
|
|
||||||
|
|
||||||
curlx_strtoofft()
|
curlx_strtoofft()
|
||||||
|
|
||||||
@@ -25,14 +24,6 @@ strtoofft.[ch]
|
|||||||
strtoll() (or equivalent) function exist on your platform. If curl_off_t
|
strtoll() (or equivalent) function exist on your platform. If curl_off_t
|
||||||
is only a 32 bit number on your platform, this macro uses strtol().
|
is only a 32 bit number on your platform, this macro uses strtol().
|
||||||
|
|
||||||
timeval.[ch]
|
|
||||||
============
|
|
||||||
|
|
||||||
Provides a 'struct timeval' for platforms that don't have one already, and
|
|
||||||
includes the proper include files for those that have one. Using this will
|
|
||||||
make the output require the 'winmm' lib on Windows (unless WITHOUT_MM_LIB
|
|
||||||
is defined at compile-time).
|
|
||||||
|
|
||||||
curlx_tvnow()
|
curlx_tvnow()
|
||||||
|
|
||||||
returns a struct timeval for the current time.
|
returns a struct timeval for the current time.
|
||||||
@@ -41,3 +32,31 @@ timeval.[ch]
|
|||||||
|
|
||||||
returns the difference between two timeval structs, in number of
|
returns the difference between two timeval structs, in number of
|
||||||
milliseconds.
|
milliseconds.
|
||||||
|
|
||||||
|
curlx_tvdiff_secs()
|
||||||
|
|
||||||
|
returns the same as curlx_tvdiff but with full usec resolution (as a
|
||||||
|
double)
|
||||||
|
|
||||||
|
FUTURE
|
||||||
|
======
|
||||||
|
|
||||||
|
Several functions will be removed from the public curl_ name space in a
|
||||||
|
future libcurl release. They will then only become available as curlx_
|
||||||
|
functions instead. To make the transition easier, we already today provide
|
||||||
|
these functions with the curlx_ prefix to allow sources to get built properly
|
||||||
|
with the new function names. The functions this concerns are:
|
||||||
|
|
||||||
|
curlx_getenv
|
||||||
|
curlx_strequal
|
||||||
|
curlx_strnequal
|
||||||
|
curlx_mvsnprintf
|
||||||
|
curlx_msnprintf
|
||||||
|
curlx_maprintf
|
||||||
|
curlx_mvaprintf
|
||||||
|
curlx_msprintf
|
||||||
|
curlx_mprintf
|
||||||
|
curlx_mfprintf
|
||||||
|
curlx_mvsprintf
|
||||||
|
curlx_mvprintf
|
||||||
|
curlx_mvfprintf
|
||||||
|
|||||||
@@ -41,10 +41,11 @@
|
|||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
/* include memdebug.h last */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
static void decodeQuantum(unsigned char *dest, const char *src)
|
static void decodeQuantum(unsigned char *dest, const char *src)
|
||||||
{
|
{
|
||||||
@@ -131,6 +132,8 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
|
|||||||
|
|
||||||
char *indata = (char *)inp;
|
char *indata = (char *)inp;
|
||||||
|
|
||||||
|
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
|
||||||
|
|
||||||
if(0 == insize)
|
if(0 == insize)
|
||||||
insize = strlen(indata);
|
insize = strlen(indata);
|
||||||
|
|
||||||
|
|||||||
101
lib/connect.c
101
lib/connect.c
@@ -96,14 +96,17 @@
|
|||||||
#include "if2ip.h"
|
#include "if2ip.h"
|
||||||
#include "strerror.h"
|
#include "strerror.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool verifyconnect(curl_socket_t sockfd);
|
static bool verifyconnect(curl_socket_t sockfd, int *error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_ourerrno() returns the errno (or equivalent) on this platform to
|
||||||
|
* hide platform specific for the function that calls this.
|
||||||
|
*/
|
||||||
int Curl_ourerrno(void)
|
int Curl_ourerrno(void)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -113,13 +116,11 @@ int Curl_ourerrno(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*
|
||||||
* Curl_nonblock
|
* Curl_nonblock() set the given socket to either blocking or non-blocking
|
||||||
*
|
* mode based on the 'nonblock' boolean argument. This function is highly
|
||||||
* Description:
|
* portable.
|
||||||
* Set the socket to either blocking or non-blocking mode.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
|
int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
|
||||||
int nonblock /* TRUE or FALSE */)
|
int nonblock /* TRUE or FALSE */)
|
||||||
{
|
{
|
||||||
@@ -177,12 +178,19 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* waitconnect() returns:
|
* waitconnect() waits for a TCP connect on the given socket for the specified
|
||||||
|
* number if milliseconds. It returns:
|
||||||
* 0 fine connect
|
* 0 fine connect
|
||||||
* -1 select() error
|
* -1 select() error
|
||||||
* 1 select() timeout
|
* 1 select() timeout
|
||||||
* 2 select() returned with an error condition
|
* 2 select() returned with an error condition fd_set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define WAITCONN_CONNECTED 0
|
||||||
|
#define WAITCONN_SELECT_ERROR -1
|
||||||
|
#define WAITCONN_TIMEOUT 1
|
||||||
|
#define WAITCONN_FDSET_ERROR 2
|
||||||
|
|
||||||
static
|
static
|
||||||
int waitconnect(curl_socket_t sockfd, /* socket */
|
int waitconnect(curl_socket_t sockfd, /* socket */
|
||||||
long timeout_msec)
|
long timeout_msec)
|
||||||
@@ -195,7 +203,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */
|
|||||||
/* Call this function once now, and ignore the results. We do this to
|
/* Call this function once now, and ignore the results. We do this to
|
||||||
"clear" the error state on the socket so that we can later read it
|
"clear" the error state on the socket so that we can later read it
|
||||||
reliably. This is reported necessary on the MPE/iX operating system. */
|
reliably. This is reported necessary on the MPE/iX operating system. */
|
||||||
verifyconnect(sockfd);
|
verifyconnect(sockfd, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* now select() until we get connect or timeout */
|
/* now select() until we get connect or timeout */
|
||||||
@@ -213,18 +221,18 @@ int waitconnect(curl_socket_t sockfd, /* socket */
|
|||||||
rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
|
rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
|
||||||
if(-1 == rc)
|
if(-1 == rc)
|
||||||
/* error, no connect here, try next */
|
/* error, no connect here, try next */
|
||||||
return -1;
|
return WAITCONN_SELECT_ERROR;
|
||||||
|
|
||||||
else if(0 == rc)
|
else if(0 == rc)
|
||||||
/* timeout, no connect today */
|
/* timeout, no connect today */
|
||||||
return 1;
|
return WAITCONN_TIMEOUT;
|
||||||
|
|
||||||
if(FD_ISSET(sockfd, &errfd))
|
if(FD_ISSET(sockfd, &errfd))
|
||||||
/* error condition caught */
|
/* error condition caught */
|
||||||
return 2;
|
return WAITCONN_FDSET_ERROR;
|
||||||
|
|
||||||
/* we have a connect! */
|
/* we have a connect! */
|
||||||
return 0;
|
return WAITCONN_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode bindlocal(struct connectdata *conn,
|
static CURLcode bindlocal(struct connectdata *conn,
|
||||||
@@ -254,7 +262,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
|
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
|
||||||
*/
|
*/
|
||||||
rc = Curl_resolv(conn, myhost, 0, &h);
|
rc = Curl_resolv(conn, myhost, 0, &h);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
(void)Curl_wait_for_resolv(conn, &h);
|
(void)Curl_wait_for_resolv(conn, &h);
|
||||||
|
|
||||||
if(h)
|
if(h)
|
||||||
@@ -267,7 +275,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
* or IP number
|
* or IP number
|
||||||
*/
|
*/
|
||||||
rc = Curl_resolv(conn, data->set.device, 0, &h);
|
rc = Curl_resolv(conn, data->set.device, 0, &h);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
(void)Curl_wait_for_resolv(conn, &h);
|
(void)Curl_wait_for_resolv(conn, &h);
|
||||||
|
|
||||||
if(h)
|
if(h)
|
||||||
@@ -389,25 +397,50 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
/*
|
/*
|
||||||
* verifyconnect() returns TRUE if the connect really has happened.
|
* verifyconnect() returns TRUE if the connect really has happened.
|
||||||
*/
|
*/
|
||||||
static bool verifyconnect(curl_socket_t sockfd)
|
static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||||
{
|
{
|
||||||
#if defined(SO_ERROR) && !defined(WIN32)
|
bool rc = TRUE;
|
||||||
|
#ifdef SO_ERROR
|
||||||
int err = 0;
|
int err = 0;
|
||||||
socklen_t errSize = sizeof(err);
|
socklen_t errSize = sizeof(err);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/*
|
||||||
|
* In October 2003 we effectively nullified this function on Windows due to
|
||||||
|
* problems with it using all CPU in multi-threaded cases.
|
||||||
|
*
|
||||||
|
* In May 2004, we bring it back to offer more info back on connect failures.
|
||||||
|
* Gisle Vanem could reproduce the former problems with this function, but
|
||||||
|
* could avoid them by adding this SleepEx() call below:
|
||||||
|
*
|
||||||
|
* "I don't have Rational Quantify, but the hint from his post was
|
||||||
|
* ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
|
||||||
|
* just Sleep(0) would be enough?) would release whatever
|
||||||
|
* mutex/critical-section the ntdll call is waiting on.
|
||||||
|
*
|
||||||
|
* Someone got to verify this on Win-NT 4.0, 2000."
|
||||||
|
*/
|
||||||
|
SleepEx(0, FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||||
(void *)&err, &errSize))
|
(void *)&err, &errSize))
|
||||||
err = Curl_ourerrno();
|
err = Curl_ourerrno();
|
||||||
|
|
||||||
if ((0 == err) || (EISCONN == err))
|
if ((0 == err) || (EISCONN == err))
|
||||||
/* we are connected, awesome! */
|
/* we are connected, awesome! */
|
||||||
return TRUE;
|
rc = TRUE;
|
||||||
|
else
|
||||||
/* This wasn't a successful connect */
|
/* This wasn't a successful connect */
|
||||||
return FALSE;
|
rc = FALSE;
|
||||||
|
if (error)
|
||||||
|
*error = err;
|
||||||
#else
|
#else
|
||||||
(void)sockfd;
|
(void)sockfd;
|
||||||
return TRUE;
|
if (error)
|
||||||
|
*error = Curl_ourerrno();
|
||||||
#endif
|
#endif
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -458,7 +491,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
rc = waitconnect(sockfd, 0);
|
rc = waitconnect(sockfd, 0);
|
||||||
|
|
||||||
if(0 == rc) {
|
if(0 == rc) {
|
||||||
if (verifyconnect(sockfd)) {
|
if (verifyconnect(sockfd,NULL)) {
|
||||||
/* we are connected, awesome! */
|
/* we are connected, awesome! */
|
||||||
*connected = TRUE;
|
*connected = TRUE;
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@@ -470,7 +503,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
else if(1 != rc) {
|
else if(1 != rc) {
|
||||||
int error = Curl_ourerrno();
|
int error = Curl_ourerrno();
|
||||||
failf(data, "Failed connect to %s:%d; %s",
|
failf(data, "Failed connect to %s:%d; %s",
|
||||||
conn->hostname, conn->port, Curl_strerror(conn,error));
|
conn->host.name, conn->port, Curl_strerror(conn,error));
|
||||||
return CURLE_COULDNT_CONNECT;
|
return CURLE_COULDNT_CONNECT;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -516,7 +549,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
bool *connected) /* really connected? */
|
bool *connected) /* really connected? */
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
int rc;
|
int rc, error;
|
||||||
curl_socket_t sockfd= CURL_SOCKET_BAD;
|
curl_socket_t sockfd= CURL_SOCKET_BAD;
|
||||||
int aliasindex=0;
|
int aliasindex=0;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
@@ -567,7 +600,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname = data->change.proxy?conn->proxyhost:conn->hostname;
|
hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
||||||
infof(data, "About to connect() to %s port %d\n",
|
infof(data, "About to connect() to %s port %d\n",
|
||||||
hostname, port);
|
hostname, port);
|
||||||
|
|
||||||
@@ -634,7 +667,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
int error=Curl_ourerrno();
|
error = Curl_ourerrno();
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case EINPROGRESS:
|
case EINPROGRESS:
|
||||||
@@ -671,7 +704,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(0 == rc) {
|
if(0 == rc) {
|
||||||
if (verifyconnect(sockfd)) {
|
if (verifyconnect(sockfd,NULL)) {
|
||||||
/* we are connected, awesome! */
|
/* we are connected, awesome! */
|
||||||
*connected = TRUE; /* this is a true connect */
|
*connected = TRUE; /* this is a true connect */
|
||||||
break;
|
break;
|
||||||
@@ -679,10 +712,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
/* nope, not connected for real */
|
/* nope, not connected for real */
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
verifyconnect(sockfd,&error); /* get non-blocking error */
|
||||||
|
|
||||||
/* connect failed or timed out */
|
/* connect failed or timed out */
|
||||||
sclose(sockfd);
|
sclose(sockfd);
|
||||||
sockfd = -1;
|
sockfd = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
/* get a new timeout for next attempt */
|
/* get a new timeout for next attempt */
|
||||||
after = Curl_tvnow();
|
after = Curl_tvnow();
|
||||||
@@ -696,7 +731,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
if (sockfd == CURL_SOCKET_BAD) {
|
if (sockfd == CURL_SOCKET_BAD) {
|
||||||
/* no good connect was made */
|
/* no good connect was made */
|
||||||
*sockconn = -1;
|
*sockconn = -1;
|
||||||
failf(data, "Connect failed; %s", Curl_strerror(conn,Curl_ourerrno()));
|
failf(data, "Connect failed; %s", Curl_strerror(conn,error));
|
||||||
return CURLE_COULDNT_CONNECT;
|
return CURLE_COULDNT_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,11 @@
|
|||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <curl/types.h>
|
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "content_encoding.h"
|
#include "content_encoding.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
#define DSIZ 0x10000 /* buffer size for decompressed data */
|
#define DSIZ 0x10000 /* buffer size for decompressed data */
|
||||||
|
|
||||||
@@ -82,7 +84,7 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
|
|||||||
if (!k->zlib_init) {
|
if (!k->zlib_init) {
|
||||||
z->zalloc = (alloc_func)Z_NULL;
|
z->zalloc = (alloc_func)Z_NULL;
|
||||||
z->zfree = (free_func)Z_NULL;
|
z->zfree = (free_func)Z_NULL;
|
||||||
z->opaque = 0; /* of dubious use 08/27/02 jhrg */
|
z->opaque = 0;
|
||||||
z->next_in = NULL;
|
z->next_in = NULL;
|
||||||
z->avail_in = 0;
|
z->avail_in = 0;
|
||||||
if (inflateInit(z) != Z_OK)
|
if (inflateInit(z) != Z_OK)
|
||||||
@@ -226,7 +228,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
|
|||||||
if (!k->zlib_init) {
|
if (!k->zlib_init) {
|
||||||
z->zalloc = (alloc_func)Z_NULL;
|
z->zalloc = (alloc_func)Z_NULL;
|
||||||
z->zfree = (free_func)Z_NULL;
|
z->zfree = (free_func)Z_NULL;
|
||||||
z->opaque = 0; /* of dubious use 08/27/02 jhrg */
|
z->opaque = 0;
|
||||||
z->next_in = NULL;
|
z->next_in = NULL;
|
||||||
z->avail_in = 0;
|
z->avail_in = 0;
|
||||||
if (inflateInit2(z, -MAX_WBITS) != Z_OK)
|
if (inflateInit2(z, -MAX_WBITS) != Z_OK)
|
||||||
@@ -235,10 +237,11 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This next mess is to get around the potential case where there isn't
|
/* This next mess is to get around the potential case where there isn't
|
||||||
enough data passed in to skip over the gzip header. If that happens,
|
* enough data passed in to skip over the gzip header. If that happens, we
|
||||||
we malloc a block and copy what we have then wait for the next call. If
|
* malloc a block and copy what we have then wait for the next call. If
|
||||||
there still isn't enough (this is definitely a worst-case scenario), we
|
* there still isn't enough (this is definitely a worst-case scenario), we
|
||||||
make the block bigger, copy the next part in and keep waiting. */
|
* make the block bigger, copy the next part in and keep waiting.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Skip over gzip header? */
|
/* Skip over gzip header? */
|
||||||
if (k->zlib_init == 1) {
|
if (k->zlib_init == 1) {
|
||||||
@@ -253,12 +256,13 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GZIP_UNDERFLOW:
|
case GZIP_UNDERFLOW:
|
||||||
/* We need more data so we can find the end of the gzip header.
|
/* We need more data so we can find the end of the gzip header. It's
|
||||||
It's possible that the memory block we malloc here will never be
|
* possible that the memory block we malloc here will never be freed if
|
||||||
freed if the transfer abruptly aborts after this point. Since it's
|
* the transfer abruptly aborts after this point. Since it's unlikely
|
||||||
unlikely that circumstances will be right for this code path to be
|
* that circumstances will be right for this code path to be followed in
|
||||||
followed in the first place, and it's even more unlikely for a transfer
|
* the first place, and it's even more unlikely for a transfer to fail
|
||||||
to fail immediately afterwards, it should seldom be a problem. */
|
* immediately afterwards, it should seldom be a problem.
|
||||||
|
*/
|
||||||
z->avail_in = nread;
|
z->avail_in = nread;
|
||||||
z->next_in = malloc(z->avail_in);
|
z->next_in = malloc(z->avail_in);
|
||||||
if (z->next_in == NULL) {
|
if (z->next_in == NULL) {
|
||||||
@@ -321,8 +325,8 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* because the buffer size is fixed, iteratively decompress
|
/* because the buffer size is fixed, iteratively decompress and transfer to
|
||||||
and transfer to the client via client_write. */
|
the client via client_write. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* (re)set buffer for decompressed output for every iteration */
|
/* (re)set buffer for decompressed output for every iteration */
|
||||||
z->next_out = (Bytef *)&decomp[0];
|
z->next_out = (Bytef *)&decomp[0];
|
||||||
|
|||||||
181
lib/cookie.c
181
lib/cookie.c
@@ -1,8 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -28,7 +28,7 @@ RECEIVING COOKIE INFORMATION
|
|||||||
============================
|
============================
|
||||||
|
|
||||||
struct CookieInfo *cookie_init(char *file);
|
struct CookieInfo *cookie_init(char *file);
|
||||||
|
|
||||||
Inits a cookie struct to store data in a local file. This is always
|
Inits a cookie struct to store data in a local file. This is always
|
||||||
called before any cookies are set.
|
called before any cookies are set.
|
||||||
|
|
||||||
@@ -58,9 +58,9 @@ struct Cookies *cookie_getlist(struct CookieInfo *cookie,
|
|||||||
|
|
||||||
It shall only return cookies that haven't expired.
|
It shall only return cookies that haven't expired.
|
||||||
|
|
||||||
|
|
||||||
Example set of cookies:
|
Example set of cookies:
|
||||||
|
|
||||||
Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
|
Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
|
||||||
Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
|
Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
|
||||||
domain=.fidelity.com; path=/ftgw; secure
|
domain=.fidelity.com; path=/ftgw; secure
|
||||||
@@ -92,15 +92,17 @@ Example set of cookies:
|
|||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
#include "strtok.h"
|
#include "strtok.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
#ifdef CURLDEBUG
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void freecookie(struct Cookie *co)
|
||||||
free_cookiemess(struct Cookie *co)
|
|
||||||
{
|
{
|
||||||
|
if(co->expirestr)
|
||||||
|
free(co->expirestr);
|
||||||
if(co->domain)
|
if(co->domain)
|
||||||
free(co->domain);
|
free(co->domain);
|
||||||
if(co->path)
|
if(co->path)
|
||||||
@@ -137,7 +139,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
/* The 'data' pointer here may be NULL at times, and thus
|
/* The 'data' pointer here may be NULL at times, and thus
|
||||||
must only be used very carefully for things that can deal
|
must only be used very carefully for things that can deal
|
||||||
with data being NULL. Such as infof() and similar */
|
with data being NULL. Such as infof() and similar */
|
||||||
|
|
||||||
struct CookieInfo *c,
|
struct CookieInfo *c,
|
||||||
bool httpheader, /* TRUE if HTTP header-style line */
|
bool httpheader, /* TRUE if HTTP header-style line */
|
||||||
char *lineptr, /* first character of the line */
|
char *lineptr, /* first character of the line */
|
||||||
@@ -203,6 +205,10 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
|
|
||||||
if(strequal("path", name)) {
|
if(strequal("path", name)) {
|
||||||
co->path=strdup(whatptr);
|
co->path=strdup(whatptr);
|
||||||
|
if(!co->path) {
|
||||||
|
badcookie = TRUE; /* out of memory bad */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(strequal("domain", name)) {
|
else if(strequal("domain", name)) {
|
||||||
/* note that this name may or may not have a preceeding dot, but
|
/* note that this name may or may not have a preceeding dot, but
|
||||||
@@ -243,7 +249,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
but it seems that these kinds of cookies are in use "out there"
|
but it seems that these kinds of cookies are in use "out there"
|
||||||
so we cannot be that strict. I've therefore lowered the check
|
so we cannot be that strict. I've therefore lowered the check
|
||||||
to not allow less than two dots. */
|
to not allow less than two dots. */
|
||||||
|
|
||||||
if(dotcount < 2) {
|
if(dotcount < 2) {
|
||||||
/* Received and skipped a cookie with a domain using too few
|
/* Received and skipped a cookie with a domain using too few
|
||||||
dots. */
|
dots. */
|
||||||
@@ -255,11 +261,19 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
/* Now, we make sure that our host is within the given domain,
|
/* Now, we make sure that our host is within the given domain,
|
||||||
or the given domain is not valid and thus cannot be set. */
|
or the given domain is not valid and thus cannot be set. */
|
||||||
|
|
||||||
|
if('.' == whatptr[0])
|
||||||
|
whatptr++; /* ignore preceeding dot */
|
||||||
|
|
||||||
if(!domain || tailmatch(whatptr, domain)) {
|
if(!domain || tailmatch(whatptr, domain)) {
|
||||||
const char *tailptr=whatptr;
|
const char *tailptr=whatptr;
|
||||||
if(tailptr[0] == '.')
|
if(tailptr[0] == '.')
|
||||||
tailptr++;
|
tailptr++;
|
||||||
co->domain=strdup(tailptr); /* don't prefix w/dots internally */
|
co->domain=strdup(tailptr); /* don't prefix w/dots
|
||||||
|
internally */
|
||||||
|
if(!co->domain) {
|
||||||
|
badcookie = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
co->tailmatch=TRUE; /* we always do that if the domain name was
|
co->tailmatch=TRUE; /* we always do that if the domain name was
|
||||||
given */
|
given */
|
||||||
}
|
}
|
||||||
@@ -275,6 +289,10 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
else if(strequal("version", name)) {
|
else if(strequal("version", name)) {
|
||||||
co->version=strdup(whatptr);
|
co->version=strdup(whatptr);
|
||||||
|
if(!co->version) {
|
||||||
|
badcookie = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(strequal("max-age", name)) {
|
else if(strequal("max-age", name)) {
|
||||||
/* Defined in RFC2109:
|
/* Defined in RFC2109:
|
||||||
@@ -287,16 +305,28 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
co->maxage = strdup(whatptr);
|
co->maxage = strdup(whatptr);
|
||||||
|
if(!co->maxage) {
|
||||||
|
badcookie = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
co->expires =
|
co->expires =
|
||||||
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
|
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
|
||||||
}
|
}
|
||||||
else if(strequal("expires", name)) {
|
else if(strequal("expires", name)) {
|
||||||
co->expirestr=strdup(whatptr);
|
co->expirestr=strdup(whatptr);
|
||||||
|
if(!co->expirestr) {
|
||||||
|
badcookie = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
co->expires = curl_getdate(what, &now);
|
co->expires = curl_getdate(what, &now);
|
||||||
}
|
}
|
||||||
else if(!co->name) {
|
else if(!co->name) {
|
||||||
co->name = strdup(name);
|
co->name = strdup(name);
|
||||||
co->value = strdup(whatptr);
|
co->value = strdup(whatptr);
|
||||||
|
if(!co->name || !co->value) {
|
||||||
|
badcookie = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
else this is the second (or more) name we don't know
|
else this is the second (or more) name we don't know
|
||||||
@@ -333,28 +363,17 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
semiptr=strchr(ptr, '\0');
|
semiptr=strchr(ptr, '\0');
|
||||||
} while(semiptr);
|
} while(semiptr);
|
||||||
|
|
||||||
if(badcookie || (NULL == co->name)) {
|
if(!badcookie && !co->domain) {
|
||||||
/* we didn't get a cookie name or a bad one,
|
if(domain) {
|
||||||
this is an illegal line, bail out */
|
/* no domain was given in the header line, set the default */
|
||||||
if(co->expirestr)
|
co->domain=strdup(domain);
|
||||||
free(co->expirestr);
|
if(!co->domain)
|
||||||
if(co->domain)
|
badcookie = TRUE;
|
||||||
free(co->domain);
|
}
|
||||||
if(co->path)
|
|
||||||
free(co->path);
|
|
||||||
if(co->name)
|
|
||||||
free(co->name);
|
|
||||||
if(co->value)
|
|
||||||
free(co->value);
|
|
||||||
free(co);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NULL == co->domain)
|
if(!badcookie && !co->path && path) {
|
||||||
/* no domain was given in the header line, set the default now */
|
/* no path was given in the header line, set the default */
|
||||||
co->domain=domain?strdup(domain):NULL;
|
|
||||||
if((NULL == co->path) && path) {
|
|
||||||
/* no path was given in the header line, set the default now */
|
|
||||||
char *endslash = strrchr(path, '/');
|
char *endslash = strrchr(path, '/');
|
||||||
if(endslash) {
|
if(endslash) {
|
||||||
size_t pathlen = endslash-path+1; /* include the ending slash */
|
size_t pathlen = endslash-path+1; /* include the ending slash */
|
||||||
@@ -363,8 +382,18 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
memcpy(co->path, path, pathlen);
|
memcpy(co->path, path, pathlen);
|
||||||
co->path[pathlen]=0; /* zero terminate */
|
co->path[pathlen]=0; /* zero terminate */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
badcookie = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(badcookie || !co->name) {
|
||||||
|
/* we didn't get a cookie name or a bad one,
|
||||||
|
this is an illegal line, bail out */
|
||||||
|
freecookie(co);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* This line is NOT a HTTP header style line, we do offer support for
|
/* This line is NOT a HTTP header style line, we do offer support for
|
||||||
@@ -386,7 +415,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
if(ptr)
|
if(ptr)
|
||||||
*ptr=0; /* clear it */
|
*ptr=0; /* clear it */
|
||||||
|
|
||||||
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* first tokenize it on the TAB */
|
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
|
||||||
|
|
||||||
/* Here's a quick check to eliminate normal HTTP-headers from this */
|
/* Here's a quick check to eliminate normal HTTP-headers from this */
|
||||||
if(!firstptr || strchr(firstptr, ':')) {
|
if(!firstptr || strchr(firstptr, ':')) {
|
||||||
@@ -396,13 +425,15 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* Now loop through the fields and init the struct we already have
|
/* Now loop through the fields and init the struct we already have
|
||||||
allocated */
|
allocated */
|
||||||
for(ptr=firstptr, fields=0; ptr;
|
for(ptr=firstptr, fields=0; ptr && !badcookie;
|
||||||
ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
|
ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
|
||||||
switch(fields) {
|
switch(fields) {
|
||||||
case 0:
|
case 0:
|
||||||
if(ptr[0]=='.') /* skip preceeding dots */
|
if(ptr[0]=='.') /* skip preceeding dots */
|
||||||
ptr++;
|
ptr++;
|
||||||
co->domain = strdup(ptr);
|
co->domain = strdup(ptr);
|
||||||
|
if(!co->domain)
|
||||||
|
badcookie = TRUE;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* This field got its explanation on the 23rd of May 2001 by
|
/* This field got its explanation on the 23rd of May 2001 by
|
||||||
@@ -424,10 +455,14 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
|
if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
|
||||||
/* only if the path doesn't look like a boolean option! */
|
/* only if the path doesn't look like a boolean option! */
|
||||||
co->path = strdup(ptr);
|
co->path = strdup(ptr);
|
||||||
|
if(!co->path)
|
||||||
|
badcookie = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* this doesn't look like a path, make one up! */
|
/* this doesn't look like a path, make one up! */
|
||||||
co->path = strdup("/");
|
co->path = strdup("/");
|
||||||
|
if(!co->path)
|
||||||
|
badcookie = TRUE;
|
||||||
fields++; /* add a field and fall down to secure */
|
fields++; /* add a field and fall down to secure */
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 3:
|
case 3:
|
||||||
@@ -438,29 +473,40 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
co->name = strdup(ptr);
|
co->name = strdup(ptr);
|
||||||
|
if(!co->name)
|
||||||
|
badcookie = TRUE;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
co->value = strdup(ptr);
|
co->value = strdup(ptr);
|
||||||
|
if(!co->value)
|
||||||
|
badcookie = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(6 == fields) {
|
if(6 == fields) {
|
||||||
/* we got a cookie with blank contents, fix it */
|
/* we got a cookie with blank contents, fix it */
|
||||||
co->value = strdup("");
|
co->value = strdup("");
|
||||||
|
if(!co->value)
|
||||||
|
badcookie = TRUE;
|
||||||
|
else
|
||||||
|
fields++;
|
||||||
}
|
}
|
||||||
else if(7 != fields) {
|
|
||||||
/* we did not find the sufficient number of fields to recognize this
|
if(!badcookie && (7 != fields))
|
||||||
as a valid line, abort and go home */
|
/* we did not find the sufficient number of fields */
|
||||||
free_cookiemess(co);
|
badcookie = TRUE;
|
||||||
|
|
||||||
|
if(badcookie) {
|
||||||
|
freecookie(co);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!c->running && /* read from a file */
|
if(!c->running && /* read from a file */
|
||||||
c->newsession && /* clean session cookies */
|
c->newsession && /* clean session cookies */
|
||||||
!co->expires) { /* this is a session cookie since it doesn't expire! */
|
!co->expires) { /* this is a session cookie since it doesn't expire! */
|
||||||
free_cookiemess(co);
|
freecookie(co);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +544,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
replace_old = TRUE;
|
replace_old = TRUE;
|
||||||
else
|
else
|
||||||
replace_old = FALSE;
|
replace_old = FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(replace_old && !co->livecookie && clist->livecookie) {
|
if(replace_old && !co->livecookie && clist->livecookie) {
|
||||||
@@ -508,16 +554,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
live cookies stay alive */
|
live cookies stay alive */
|
||||||
|
|
||||||
/* Free the newcomer and get out of here! */
|
/* Free the newcomer and get out of here! */
|
||||||
if(co->domain)
|
freecookie(co);
|
||||||
free(co->domain);
|
|
||||||
if(co->path)
|
|
||||||
free(co->path);
|
|
||||||
if(co->name)
|
|
||||||
free(co->name);
|
|
||||||
if(co->value)
|
|
||||||
free(co->value);
|
|
||||||
|
|
||||||
free(co);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,7 +633,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
|
|||||||
struct CookieInfo *c;
|
struct CookieInfo *c;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
bool fromfile=TRUE;
|
bool fromfile=TRUE;
|
||||||
|
|
||||||
if(NULL == inc) {
|
if(NULL == inc) {
|
||||||
/* we didn't get a struct, create one */
|
/* we didn't get a struct, create one */
|
||||||
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
|
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
|
||||||
@@ -678,14 +715,14 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
continue if we are! */
|
continue if we are! */
|
||||||
if( (co->expires<=0 || (co->expires> now)) &&
|
if( (co->expires<=0 || (co->expires> now)) &&
|
||||||
(co->secure?secure:TRUE) ) {
|
(co->secure?secure:TRUE) ) {
|
||||||
|
|
||||||
/* now check if the domain is correct */
|
/* now check if the domain is correct */
|
||||||
if(!co->domain ||
|
if(!co->domain ||
|
||||||
(co->tailmatch && tailmatch(co->domain, host)) ||
|
(co->tailmatch && tailmatch(co->domain, host)) ||
|
||||||
(!co->tailmatch && strequal(host, co->domain)) ) {
|
(!co->tailmatch && strequal(host, co->domain)) ) {
|
||||||
/* the right part of the host matches the domain stuff in the
|
/* the right part of the host matches the domain stuff in the
|
||||||
cookie data */
|
cookie data */
|
||||||
|
|
||||||
/* now check the left part of the path with the cookies path
|
/* now check the left part of the path with the cookies path
|
||||||
requirement */
|
requirement */
|
||||||
if(!co->path ||
|
if(!co->path ||
|
||||||
@@ -693,7 +730,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
|
|
||||||
/* and now, we know this is a match and we should create an
|
/* and now, we know this is a match and we should create an
|
||||||
entry for the return-linked-list */
|
entry for the return-linked-list */
|
||||||
|
|
||||||
newco = (struct Cookie *)malloc(sizeof(struct Cookie));
|
newco = (struct Cookie *)malloc(sizeof(struct Cookie));
|
||||||
if(newco) {
|
if(newco) {
|
||||||
/* first, copy the whole source cookie: */
|
/* first, copy the whole source cookie: */
|
||||||
@@ -701,10 +738,20 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
|
|
||||||
/* then modify our next */
|
/* then modify our next */
|
||||||
newco->next = mainco;
|
newco->next = mainco;
|
||||||
|
|
||||||
/* point the main to us */
|
/* point the main to us */
|
||||||
mainco = newco;
|
mainco = newco;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* failure, clear up the allocated chain and return NULL */
|
||||||
|
while(mainco) {
|
||||||
|
co = mainco->next;
|
||||||
|
free(mainco);
|
||||||
|
mainco = co;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -753,24 +800,8 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
|
|||||||
co = c->cookies;
|
co = c->cookies;
|
||||||
|
|
||||||
while(co) {
|
while(co) {
|
||||||
if(co->name)
|
|
||||||
free(co->name);
|
|
||||||
if(co->value)
|
|
||||||
free(co->value);
|
|
||||||
if(co->domain)
|
|
||||||
free(co->domain);
|
|
||||||
if(co->path)
|
|
||||||
free(co->path);
|
|
||||||
if(co->expirestr)
|
|
||||||
free(co->expirestr);
|
|
||||||
|
|
||||||
if(co->version)
|
|
||||||
free(co->version);
|
|
||||||
if(co->maxage)
|
|
||||||
free(co->maxage);
|
|
||||||
|
|
||||||
next = co->next;
|
next = co->next;
|
||||||
free(co);
|
freecookie(co);
|
||||||
co = next;
|
co = next;
|
||||||
}
|
}
|
||||||
free(c); /* free the base struct as well */
|
free(c); /* free the base struct as well */
|
||||||
@@ -813,7 +844,7 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
|
|||||||
"# This file was generated by libcurl! Edit at your own risk.\n\n",
|
"# This file was generated by libcurl! Edit at your own risk.\n\n",
|
||||||
out);
|
out);
|
||||||
co = c->cookies;
|
co = c->cookies;
|
||||||
|
|
||||||
while(co) {
|
while(co) {
|
||||||
fprintf(out,
|
fprintf(out,
|
||||||
"%s%s\t" /* domain */
|
"%s%s\t" /* domain */
|
||||||
|
|||||||
422
lib/curllib.dsp
422
lib/curllib.dsp
@@ -1,422 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=curllib - Win32 Debug
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "curllib.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "curllib - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "." /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /D "_WINDLL" /FR /FD /c
|
|
||||||
# SUBTRACT CPP /YX
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
|
|
||||||
# SUBTRACT CPP /WX /YX
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
|
||||||
# SUBTRACT LINK32 /nodefaultlib
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "curllib - Win32 Release"
|
|
||||||
# Name "curllib - Win32 Debug"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\base64.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\connect.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\cookie.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\dict.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\easy.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\escape.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\file.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\formdata.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ftp.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\getdate.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\getenv.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\getinfo.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\hash.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\hostip.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_chunks.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\if2ip.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\krb4.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ldap.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\libcurl.def
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\llist.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\memdebug.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\mprintf.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\multi.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\netrc.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\progress.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\security.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\sendf.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\speedcheck.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ssluse.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\strequal.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\strtok.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\telnet.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\timeval.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\transfer.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\url.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\share.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\version.c
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\arpa_telnet.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\base64.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\connect.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\cookie.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\dict.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\escape.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\file.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\formdata.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ftp.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\getdate.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\getenv.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\hostip.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_chunks.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\if2ip.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\inet_ntoa_r.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\krb4.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ldap.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\memdebug.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\netrc.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\progress.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\security.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\sendf.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\setup.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\speedcheck.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\ssluse.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\strequal.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\strtok.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\telnet.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\timeval.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\transfer.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\url.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\urldata.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_digest.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_ntlm.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_ntlm.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\inet_pton.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\inet_pton.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\md5.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\http_digest.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\md5.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
95
lib/curlx.h
Normal file
95
lib/curlx.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#ifndef __CURLX_H
|
||||||
|
#define __CURLX_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines protos and includes all header files that provide the curlx_*
|
||||||
|
* functions. The curlx_* functions are not part of the libcurl API, but are
|
||||||
|
* stand-alone functions whose sources can be built and linked by apps if need
|
||||||
|
* be.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
/* this is still a public header file that provides the curl_mprintf()
|
||||||
|
functions while they still are offered publicly. They will be made library-
|
||||||
|
private one day */
|
||||||
|
|
||||||
|
#include "strequal.h"
|
||||||
|
/* "strequal.h" provides the strequal protos */
|
||||||
|
|
||||||
|
#include "strtoofft.h"
|
||||||
|
/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
|
||||||
|
curl_off_t number from a given string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "timeval.h"
|
||||||
|
/*
|
||||||
|
"timeval.h" sets up a 'struct timeval' even for platforms that otherwise
|
||||||
|
don't have one and has protos for these functions:
|
||||||
|
|
||||||
|
curlx_tvnow()
|
||||||
|
curlx_tvdiff()
|
||||||
|
curlx_tvdiff_secs()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Now setup curlx_ * names for the functions that are to become curlx_ and
|
||||||
|
be removed from a future libcurl official API:
|
||||||
|
curlx_getenv
|
||||||
|
curlx_mprintf (and its variations)
|
||||||
|
curlx_strequal
|
||||||
|
curlx_strnequal
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define curlx_getenv curl_getenv
|
||||||
|
#define curlx_strequal curl_strequal
|
||||||
|
#define curlx_strnequal curl_strnequal
|
||||||
|
#define curlx_mvsnprintf curl_mvsnprintf
|
||||||
|
#define curlx_msnprintf curl_msnprintf
|
||||||
|
#define curlx_maprintf curl_maprintf
|
||||||
|
#define curlx_mvaprintf curl_mvaprintf
|
||||||
|
#define curlx_msprintf curl_msprintf
|
||||||
|
#define curlx_mprintf curl_mprintf
|
||||||
|
#define curlx_mfprintf curl_mfprintf
|
||||||
|
#define curlx_mvsprintf curl_mvsprintf
|
||||||
|
#define curlx_mvprintf curl_mvprintf
|
||||||
|
#define curlx_mvfprintf curl_mvfprintf
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURLX_PRINTF
|
||||||
|
/* If this define is set, we define all "standard" printf() functions to use
|
||||||
|
the curlx_* version instead. It makes the source code transparant and
|
||||||
|
easier to understand/patch. */
|
||||||
|
# define printf curlx_mprintf
|
||||||
|
# define fprintf curlx_mfprintf
|
||||||
|
# define sprintf curlx_msprintf
|
||||||
|
# define snprintf curlx_msnprintf
|
||||||
|
# define vprintf curlx_mvprintf
|
||||||
|
# define vfprintf curlx_mvfprintf
|
||||||
|
# define vsprintf curlx_mvsprintf
|
||||||
|
# define vsnprintf curlx_mvsnprintf
|
||||||
|
# define aprintf curlx_maprintf
|
||||||
|
# define vaprintf curlx_mvaprintf
|
||||||
|
#endif /* ENABLE_CURLX_PRINTF */
|
||||||
|
|
||||||
|
#endif /* __CURLX_H */
|
||||||
257
lib/easy.c
257
lib/easy.c
@@ -66,7 +66,7 @@
|
|||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif /* WIN32 ... */
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
@@ -76,23 +76,24 @@
|
|||||||
#include "getinfo.h"
|
#include "getinfo.h"
|
||||||
#include "hostip.h"
|
#include "hostip.h"
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Silly win32 socket initialization functions */
|
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
|
||||||
|
of win32_init() */
|
||||||
static void win32_cleanup(void)
|
static void win32_cleanup(void)
|
||||||
{
|
{
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* win32_init() performs win32 socket initialization to properly setup the
|
||||||
|
stack to allow networking */
|
||||||
static CURLcode win32_init(void)
|
static CURLcode win32_init(void)
|
||||||
{
|
{
|
||||||
WORD wVersionRequested;
|
WORD wVersionRequested;
|
||||||
@@ -126,29 +127,68 @@ static CURLcode win32_init(void)
|
|||||||
WSACleanup();
|
WSACleanup();
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
|
/* The Windows Sockets DLL is acceptable. Proceed. */
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
/* The Windows Sockets DLL is acceptable. Proceed. */
|
|
||||||
#else
|
#else
|
||||||
/* These functions exist merely to prevent compiler warnings */
|
/* These functions exist merely to prevent compiler warnings */
|
||||||
static CURLcode win32_init(void) { return CURLE_OK; }
|
static CURLcode win32_init(void) { return CURLE_OK; }
|
||||||
static void win32_cleanup(void) { }
|
static void win32_cleanup(void) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LIBIDN
|
||||||
|
/*
|
||||||
|
* Initialise use of IDNA library.
|
||||||
|
* It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
|
||||||
|
* idna_to_ascii_lz().
|
||||||
|
*/
|
||||||
|
static void idna_init (void)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
char buf[60];
|
||||||
|
UINT cp = GetACP();
|
||||||
|
|
||||||
|
if (!getenv("CHARSET") && cp > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
|
||||||
|
putenv(buf);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* to do? */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* USE_LIBIDN */
|
||||||
|
|
||||||
/* true globals -- for curl_global_init() and curl_global_cleanup() */
|
/* true globals -- for curl_global_init() and curl_global_cleanup() */
|
||||||
static unsigned int initialized = 0;
|
static unsigned int initialized = 0;
|
||||||
static long init_flags = 0;
|
static long init_flags = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a memory-using function (like curl_getenv) is used before
|
||||||
|
* curl_global_init() is called, we need to have these pointers set already.
|
||||||
|
*/
|
||||||
|
curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
|
||||||
|
curl_free_callback Curl_cfree = (curl_free_callback)free;
|
||||||
|
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
|
||||||
|
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
|
||||||
|
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globally initializes cURL given a bitwise set of
|
* curl_global_init() globally initializes cURL given a bitwise set of the
|
||||||
* the different features to initialize.
|
* different features of what to initialize.
|
||||||
*/
|
*/
|
||||||
CURLcode curl_global_init(long flags)
|
CURLcode curl_global_init(long flags)
|
||||||
{
|
{
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
|
/* Setup the default memory functions here (again) */
|
||||||
|
Curl_cmalloc = (curl_malloc_callback)malloc;
|
||||||
|
Curl_cfree = (curl_free_callback)free;
|
||||||
|
Curl_crealloc = (curl_realloc_callback)realloc;
|
||||||
|
Curl_cstrdup = (curl_strdup_callback)strdup;
|
||||||
|
Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||||
|
|
||||||
if (flags & CURL_GLOBAL_SSL)
|
if (flags & CURL_GLOBAL_SSL)
|
||||||
Curl_SSL_init();
|
Curl_SSL_init();
|
||||||
|
|
||||||
@@ -161,15 +201,50 @@ CURLcode curl_global_init(long flags)
|
|||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LIBIDN
|
||||||
|
idna_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
init_flags = flags;
|
init_flags = flags;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_global_init_mem() globally initializes cURL and also registers the
|
||||||
|
* user provided callback routines.
|
||||||
|
*/
|
||||||
|
CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
|
||||||
|
curl_free_callback f, curl_realloc_callback r,
|
||||||
|
curl_strdup_callback s, curl_calloc_callback c)
|
||||||
|
{
|
||||||
|
CURLcode code = CURLE_OK;
|
||||||
|
|
||||||
|
/* Invalid input, return immediately */
|
||||||
|
if (!m || !f || !r || !s || !c)
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
|
||||||
|
/* Already initialized, don't do it again */
|
||||||
|
if ( initialized )
|
||||||
|
return CURLE_OK;
|
||||||
|
|
||||||
|
/* Call the actual init function first */
|
||||||
|
code = curl_global_init(flags);
|
||||||
|
if (code == CURLE_OK) {
|
||||||
|
Curl_cmalloc = m;
|
||||||
|
Curl_cfree = f;
|
||||||
|
Curl_cstrdup = s;
|
||||||
|
Curl_crealloc = r;
|
||||||
|
Curl_ccalloc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globally cleanup cURL, uses the value of "init_flags" to determine
|
* curl_global_cleanup() globally cleanups cURL, uses the value of
|
||||||
* what needs to be cleaned up and what doesn't
|
* "init_flags" to determine what needs to be cleaned up and what doesn't.
|
||||||
*/
|
*/
|
||||||
void curl_global_cleanup(void)
|
void curl_global_cleanup(void)
|
||||||
{
|
{
|
||||||
@@ -192,6 +267,10 @@ void curl_global_cleanup(void)
|
|||||||
init_flags = 0;
|
init_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_init() is the external interface to alloc, setup and init an
|
||||||
|
* easy handle that is returned. If anything goes wrong, NULL is returned.
|
||||||
|
*/
|
||||||
CURL *curl_easy_init(void)
|
CURL *curl_easy_init(void)
|
||||||
{
|
{
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
@@ -213,6 +292,10 @@ CURL *curl_easy_init(void)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_setopt() is the external interface for setting options on an
|
||||||
|
* easy handle.
|
||||||
|
*/
|
||||||
typedef int (*func_T)(void);
|
typedef int (*func_T)(void);
|
||||||
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
||||||
{
|
{
|
||||||
@@ -224,6 +307,9 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
|||||||
struct SessionHandle *data = curl;
|
struct SessionHandle *data = curl;
|
||||||
CURLcode ret=CURLE_FAILED_INIT;
|
CURLcode ret=CURLE_FAILED_INIT;
|
||||||
|
|
||||||
|
if(!curl)
|
||||||
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
|
||||||
va_start(arg, tag);
|
va_start(arg, tag);
|
||||||
|
|
||||||
/* PORTING NOTE:
|
/* PORTING NOTE:
|
||||||
@@ -257,10 +343,17 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_perform() is the external interface that performs a transfer
|
||||||
|
* previously setup.
|
||||||
|
*/
|
||||||
CURLcode curl_easy_perform(CURL *curl)
|
CURLcode curl_easy_perform(CURL *curl)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = (struct SessionHandle *)curl;
|
struct SessionHandle *data = (struct SessionHandle *)curl;
|
||||||
|
|
||||||
|
if(!data)
|
||||||
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
|
||||||
if ( ! (data->share && data->share->hostcache) ) {
|
if ( ! (data->share && data->share->hostcache) ) {
|
||||||
|
|
||||||
if (Curl_global_host_cache_use(data) &&
|
if (Curl_global_host_cache_use(data) &&
|
||||||
@@ -285,9 +378,17 @@ CURLcode curl_easy_perform(CURL *curl)
|
|||||||
return Curl_perform(data);
|
return Curl_perform(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
|
||||||
|
* easy handle.
|
||||||
|
*/
|
||||||
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(!data)
|
||||||
|
return;
|
||||||
|
|
||||||
if ( ! (data->share && data->share->hostcache) ) {
|
if ( ! (data->share && data->share->hostcache) ) {
|
||||||
if ( !Curl_global_host_cache_use(data)) {
|
if ( !Curl_global_host_cache_use(data)) {
|
||||||
Curl_hash_destroy(data->hostcache);
|
Curl_hash_destroy(data->hostcache);
|
||||||
@@ -296,6 +397,10 @@ void curl_easy_cleanup(CURL *curl)
|
|||||||
Curl_close(data);
|
Curl_close(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_getinfo() is an external interface that allows an app to retrieve
|
||||||
|
* information from a performed transfer and similar.
|
||||||
|
*/
|
||||||
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
|
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
@@ -308,68 +413,108 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
|
|||||||
return Curl_getinfo(data, info, paramp);
|
return Curl_getinfo(data, info, paramp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_easy_duphandle() is an external interface to allow duplication of a
|
||||||
|
* given input easy handle. The returned handle will be a new working handle
|
||||||
|
* with all options set exactly as the input source handle.
|
||||||
|
*/
|
||||||
CURL *curl_easy_duphandle(CURL *incurl)
|
CURL *curl_easy_duphandle(CURL *incurl)
|
||||||
{
|
{
|
||||||
|
bool fail = TRUE;
|
||||||
struct SessionHandle *data=(struct SessionHandle *)incurl;
|
struct SessionHandle *data=(struct SessionHandle *)incurl;
|
||||||
|
|
||||||
struct SessionHandle *outcurl = (struct SessionHandle *)
|
struct SessionHandle *outcurl = (struct SessionHandle *)
|
||||||
malloc(sizeof(struct SessionHandle));
|
calloc(sizeof(struct SessionHandle), 1);
|
||||||
|
|
||||||
if(NULL == outcurl)
|
if(NULL == outcurl)
|
||||||
return NULL; /* failure */
|
return NULL; /* failure */
|
||||||
|
|
||||||
/* start with clearing the entire new struct */
|
do {
|
||||||
memset(outcurl, 0, sizeof(struct SessionHandle));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We setup a few buffers we need. We should probably make them
|
* We setup a few buffers we need. We should probably make them
|
||||||
* get setup on-demand in the code, as that would probably decrease
|
* get setup on-demand in the code, as that would probably decrease
|
||||||
* the likeliness of us forgetting to init a buffer here in the future.
|
* the likeliness of us forgetting to init a buffer here in the future.
|
||||||
*/
|
*/
|
||||||
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
|
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
|
||||||
if(!outcurl->state.headerbuff) {
|
if(!outcurl->state.headerbuff) {
|
||||||
free(outcurl); /* free the memory again */
|
break;
|
||||||
return NULL;
|
}
|
||||||
}
|
outcurl->state.headersize=HEADERSIZE;
|
||||||
outcurl->state.headersize=HEADERSIZE;
|
|
||||||
|
|
||||||
/* copy all userdefined values */
|
/* copy all userdefined values */
|
||||||
outcurl->set = data->set;
|
outcurl->set = data->set;
|
||||||
outcurl->state.numconnects = data->state.numconnects;
|
outcurl->state.numconnects = data->state.numconnects;
|
||||||
outcurl->state.connects = (struct connectdata **)
|
outcurl->state.connects = (struct connectdata **)
|
||||||
malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
|
malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
|
||||||
|
|
||||||
if(!outcurl->state.connects) {
|
if(!outcurl->state.connects) {
|
||||||
free(outcurl->state.headerbuff);
|
break;
|
||||||
free(outcurl);
|
}
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(outcurl->state.connects, 0,
|
|
||||||
sizeof(struct connectdata *)*outcurl->state.numconnects);
|
|
||||||
|
|
||||||
outcurl->progress.flags = data->progress.flags;
|
memset(outcurl->state.connects, 0,
|
||||||
outcurl->progress.callback = data->progress.callback;
|
sizeof(struct connectdata *)*outcurl->state.numconnects);
|
||||||
|
|
||||||
if(data->cookies)
|
outcurl->progress.flags = data->progress.flags;
|
||||||
/* If cookies are enabled in the parent handle, we enable them
|
outcurl->progress.callback = data->progress.callback;
|
||||||
in the clone as well! */
|
|
||||||
outcurl->cookies = Curl_cookie_init(data,
|
|
||||||
data->cookies->filename,
|
|
||||||
outcurl->cookies,
|
|
||||||
data->set.cookiesession);
|
|
||||||
|
|
||||||
/* duplicate all values in 'change' */
|
if(data->cookies) {
|
||||||
if(data->change.url) {
|
/* If cookies are enabled in the parent handle, we enable them
|
||||||
outcurl->change.url = strdup(data->change.url);
|
in the clone as well! */
|
||||||
outcurl->change.url_alloc = TRUE;
|
outcurl->cookies = Curl_cookie_init(data,
|
||||||
}
|
data->cookies->filename,
|
||||||
if(data->change.proxy) {
|
outcurl->cookies,
|
||||||
outcurl->change.proxy = strdup(data->change.proxy);
|
data->set.cookiesession);
|
||||||
outcurl->change.proxy_alloc = TRUE;
|
if(!outcurl->cookies) {
|
||||||
}
|
break;
|
||||||
if(data->change.referer) {
|
}
|
||||||
outcurl->change.referer = strdup(data->change.referer);
|
}
|
||||||
outcurl->change.referer_alloc = TRUE;
|
|
||||||
|
/* duplicate all values in 'change' */
|
||||||
|
if(data->change.url) {
|
||||||
|
outcurl->change.url = strdup(data->change.url);
|
||||||
|
if(!outcurl->change.url)
|
||||||
|
break;
|
||||||
|
outcurl->change.url_alloc = TRUE;
|
||||||
|
}
|
||||||
|
if(data->change.proxy) {
|
||||||
|
outcurl->change.proxy = strdup(data->change.proxy);
|
||||||
|
if(!outcurl->change.proxy)
|
||||||
|
break;
|
||||||
|
outcurl->change.proxy_alloc = TRUE;
|
||||||
|
}
|
||||||
|
if(data->change.referer) {
|
||||||
|
outcurl->change.referer = strdup(data->change.referer);
|
||||||
|
if(!outcurl->change.referer)
|
||||||
|
break;
|
||||||
|
outcurl->change.referer_alloc = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ARES
|
||||||
|
/* If we use ares, we setup a new ares channel for the new handle */
|
||||||
|
if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fail = FALSE; /* we reach this point and thus we are OK */
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
if(fail) {
|
||||||
|
if(outcurl) {
|
||||||
|
if(outcurl->state.connects)
|
||||||
|
free(outcurl->state.connects);
|
||||||
|
if(outcurl->state.headerbuff)
|
||||||
|
free(outcurl->state.headerbuff);
|
||||||
|
if(outcurl->change.proxy)
|
||||||
|
free(outcurl->change.proxy);
|
||||||
|
if(outcurl->change.url)
|
||||||
|
free(outcurl->change.url);
|
||||||
|
if(outcurl->change.referer)
|
||||||
|
free(outcurl->change.referer);
|
||||||
|
free(outcurl); /* free the memory again */
|
||||||
|
outcurl = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outcurl;
|
return outcurl;
|
||||||
|
|||||||
15
lib/escape.c
15
lib/escape.c
@@ -31,21 +31,24 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
char *curl_escape(const char *string, int length)
|
char *curl_escape(const char *string, int length)
|
||||||
{
|
{
|
||||||
size_t alloc = (length?(size_t)length:strlen(string))+1;
|
size_t alloc = (length?(size_t)length:strlen(string))+1;
|
||||||
char *ns = malloc(alloc);
|
char *ns;
|
||||||
char *testing_ptr = NULL;
|
char *testing_ptr = NULL;
|
||||||
unsigned char in;
|
unsigned char in;
|
||||||
size_t newlen = alloc;
|
size_t newlen = alloc;
|
||||||
int strindex=0;
|
int strindex=0;
|
||||||
|
|
||||||
|
ns = malloc(alloc);
|
||||||
|
if(!ns)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
length = alloc-1;
|
length = alloc-1;
|
||||||
while(length--) {
|
while(length--) {
|
||||||
in = *string;
|
in = *string;
|
||||||
@@ -91,9 +94,8 @@ char *curl_unescape(const char *string, int length)
|
|||||||
int strindex=0;
|
int strindex=0;
|
||||||
long hex;
|
long hex;
|
||||||
|
|
||||||
if( !ns ) {
|
if( !ns )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
while(--alloc > 0) {
|
while(--alloc > 0) {
|
||||||
in = *string;
|
in = *string;
|
||||||
@@ -124,5 +126,6 @@ char *curl_unescape(const char *string, int length)
|
|||||||
the library's memory system */
|
the library's memory system */
|
||||||
void curl_free(void *p)
|
void curl_free(void *p)
|
||||||
{
|
{
|
||||||
free(p);
|
if(p)
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
|
|||||||
135
lib/file.c
135
lib/file.c
@@ -1,8 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -73,7 +73,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
@@ -84,17 +83,21 @@
|
|||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "speedcheck.h"
|
#include "speedcheck.h"
|
||||||
#include "getinfo.h"
|
#include "getinfo.h"
|
||||||
#include "transfer.h" /* for Curl_readwrite_init() */
|
#include "transfer.h"
|
||||||
|
#include "url.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Emulate a connect-then-transfer protocol. We connect to the file here */
|
/*
|
||||||
|
* Curl_file_connect() gets called from Curl_protocol_connect() to allow us to
|
||||||
|
* do protocol-specific actions at connect-time. We emulate a
|
||||||
|
* connect-then-transfer protocol and "connect" to the file here
|
||||||
|
*/
|
||||||
CURLcode Curl_file_connect(struct connectdata *conn)
|
CURLcode Curl_file_connect(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
char *real_path = curl_unescape(conn->path, 0);
|
char *real_path = curl_unescape(conn->path, 0);
|
||||||
@@ -105,10 +108,15 @@ CURLcode Curl_file_connect(struct connectdata *conn)
|
|||||||
char *actual_path;
|
char *actual_path;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
|
if(!real_path)
|
||||||
if(!file)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
|
||||||
|
if(!file) {
|
||||||
|
free(real_path);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
conn->proto.file = file;
|
conn->proto.file = file;
|
||||||
|
|
||||||
#if defined(WIN32) || defined(__EMX__)
|
#if defined(WIN32) || defined(__EMX__)
|
||||||
@@ -141,13 +149,16 @@ CURLcode Curl_file_connect(struct connectdata *conn)
|
|||||||
actual_path[i] = '\\';
|
actual_path[i] = '\\';
|
||||||
|
|
||||||
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
|
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
|
||||||
|
file->path = actual_path;
|
||||||
#else
|
#else
|
||||||
fd = open(real_path, O_RDONLY);
|
fd = open(real_path, O_RDONLY);
|
||||||
|
file->path = real_path;
|
||||||
#endif
|
#endif
|
||||||
free(real_path);
|
file->freepath = real_path; /* free this when done */
|
||||||
|
|
||||||
if(fd == -1) {
|
if(!conn->data->set.upload && (fd == -1)) {
|
||||||
failf(conn->data, "Couldn't open file %s", conn->path);
|
failf(conn->data, "Couldn't open file %s", conn->path);
|
||||||
|
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
|
||||||
return CURLE_FILE_COULDNT_READ_FILE;
|
return CURLE_FILE_COULDNT_READ_FILE;
|
||||||
}
|
}
|
||||||
file->fd = fd;
|
file->fd = fd;
|
||||||
@@ -159,11 +170,94 @@ CURLcode Curl_file_connect(struct connectdata *conn)
|
|||||||
#define lseek(x,y,z) _lseeki64(x, y, z)
|
#define lseek(x,y,z) _lseeki64(x, y, z)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is the do-phase, separated from the connect-phase above */
|
CURLcode Curl_file_done(struct connectdata *conn,
|
||||||
|
CURLcode status)
|
||||||
|
{
|
||||||
|
struct FILEPROTO *file = conn->proto.file;
|
||||||
|
(void)status; /* not used */
|
||||||
|
Curl_safefree(file->path);
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CURLcode file_upload(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
struct FILEPROTO *file = conn->proto.file;
|
||||||
|
char *dir = strchr(file->path, '/');
|
||||||
|
FILE *fp;
|
||||||
|
CURLcode res=CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
char *buf = data->state.buffer;
|
||||||
|
size_t nread;
|
||||||
|
size_t nwrite;
|
||||||
|
curl_off_t bytecount = 0;
|
||||||
|
struct timeval now = Curl_tvnow();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since FILE: doesn't do the full init, we need to provide some extra
|
||||||
|
* assignments here.
|
||||||
|
*/
|
||||||
|
conn->fread = data->set.fread;
|
||||||
|
conn->fread_in = data->set.in;
|
||||||
|
conn->upload_fromhere = buf;
|
||||||
|
|
||||||
|
if(!dir)
|
||||||
|
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
|
||||||
|
|
||||||
|
if(!dir[1])
|
||||||
|
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
|
||||||
|
|
||||||
|
fp = fopen(file->path, "wb");
|
||||||
|
if(!fp) {
|
||||||
|
failf(data, "Can't open %s for writing", file->path);
|
||||||
|
return CURLE_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-1 != data->set.infilesize)
|
||||||
|
/* known size of data to "upload" */
|
||||||
|
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||||
|
|
||||||
|
while (res == CURLE_OK) {
|
||||||
|
nread = Curl_fillreadbuffer(conn, BUFSIZE);
|
||||||
|
|
||||||
|
if (nread <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* write the data to the target */
|
||||||
|
nwrite = fwrite(buf, 1, nread, fp);
|
||||||
|
if(nwrite != nread) {
|
||||||
|
res = CURLE_SEND_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytecount += nread;
|
||||||
|
|
||||||
|
Curl_pgrsSetUploadCounter(data, bytecount);
|
||||||
|
|
||||||
|
if(Curl_pgrsUpdate(conn))
|
||||||
|
res = CURLE_ABORTED_BY_CALLBACK;
|
||||||
|
else
|
||||||
|
res = Curl_speedcheck(data, now);
|
||||||
|
}
|
||||||
|
if(!res && Curl_pgrsUpdate(conn))
|
||||||
|
res = CURLE_ABORTED_BY_CALLBACK;
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_file() is the protocol-specific function for the do-phase, separated
|
||||||
|
* from the connect-phase above. Other protocols merely setup the transfer in
|
||||||
|
* the do-phase, to have it done in the main transfer loop but since some
|
||||||
|
* platforms we support don't allow select()ing etc on file handles (as
|
||||||
|
* opposed to sockets) we instead perform the whole do-operation in this
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
CURLcode Curl_file(struct connectdata *conn)
|
CURLcode Curl_file(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
/* This implementation ignores the host name in conformance with
|
/* This implementation ignores the host name in conformance with
|
||||||
RFC 1738. Only local files (reachable via the standard file system)
|
RFC 1738. Only local files (reachable via the standard file system)
|
||||||
are supported. This means that files on remotely mounted directories
|
are supported. This means that files on remotely mounted directories
|
||||||
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
|
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
|
||||||
@@ -183,6 +277,9 @@ CURLcode Curl_file(struct connectdata *conn)
|
|||||||
Curl_initinfo(data);
|
Curl_initinfo(data);
|
||||||
Curl_pgrsStartNow(data);
|
Curl_pgrsStartNow(data);
|
||||||
|
|
||||||
|
if(data->set.upload)
|
||||||
|
return file_upload(conn);
|
||||||
|
|
||||||
/* get the fd from the connection phase */
|
/* get the fd from the connection phase */
|
||||||
fd = conn->proto.file->fd;
|
fd = conn->proto.file->fd;
|
||||||
|
|
||||||
@@ -259,10 +356,6 @@ CURLcode Curl_file(struct connectdata *conn)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
bytecount += nread;
|
bytecount += nread;
|
||||||
/* NOTE: The following call to fwrite does CR/LF translation on
|
|
||||||
Windows systems if the target is stdout. Use -O or -o parameters
|
|
||||||
to prevent CR/LF translation (this then goes to a binary mode
|
|
||||||
file descriptor). */
|
|
||||||
|
|
||||||
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
|
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
|
||||||
if(res)
|
if(res)
|
||||||
@@ -273,7 +366,7 @@ CURLcode Curl_file(struct connectdata *conn)
|
|||||||
if(Curl_pgrsUpdate(conn))
|
if(Curl_pgrsUpdate(conn))
|
||||||
res = CURLE_ABORTED_BY_CALLBACK;
|
res = CURLE_ABORTED_BY_CALLBACK;
|
||||||
else
|
else
|
||||||
res = Curl_speedcheck (data, now);
|
res = Curl_speedcheck(data, now);
|
||||||
}
|
}
|
||||||
if(Curl_pgrsUpdate(conn))
|
if(Curl_pgrsUpdate(conn))
|
||||||
res = CURLE_ABORTED_BY_CALLBACK;
|
res = CURLE_ABORTED_BY_CALLBACK;
|
||||||
|
|||||||
@@ -24,7 +24,8 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef CURL_DISABLE_FILE
|
#ifndef CURL_DISABLE_FILE
|
||||||
CURLcode Curl_file(struct connectdata *conn);
|
CURLcode Curl_file(struct connectdata *);
|
||||||
CURLcode Curl_file_connect(struct connectdata *conn);
|
CURLcode Curl_file_done(struct connectdata *, CURLcode);
|
||||||
|
CURLcode Curl_file_connect(struct connectdata *);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
569
lib/formdata.c
569
lib/formdata.c
@@ -97,14 +97,6 @@ Content-Type: text/plain
|
|||||||
Content-Disposition: form-data; name="FILECONTENT"
|
Content-Disposition: form-data; name="FILECONTENT"
|
||||||
...
|
...
|
||||||
|
|
||||||
For the old FormParse used by curl_formparse use:
|
|
||||||
|
|
||||||
gcc -DHAVE_CONFIG_H -I../ -g -D_OLD_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
|
|
||||||
|
|
||||||
run the 'formdata' executable and make sure the output is ok!
|
|
||||||
|
|
||||||
try './formdata "name=Daniel" "poo=noo" "foo=bar"' and similarly
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
@@ -115,21 +107,17 @@ Content-Disposition: form-data; name="FILECONTENT"
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifndef CURL_OLDSTYLE
|
|
||||||
#define CURL_OLDSTYLE 1 /* enable deprecated prototype for curl_formparse */
|
|
||||||
#endif
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "formdata.h"
|
#include "formdata.h"
|
||||||
|
|
||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Length of the random boundary string. */
|
/* Length of the random boundary string. */
|
||||||
#define BOUNDARY_LENGTH 40
|
#define BOUNDARY_LENGTH 40
|
||||||
@@ -138,255 +126,9 @@ Content-Disposition: form-data; name="FILECONTENT"
|
|||||||
extensions. */
|
extensions. */
|
||||||
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
|
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
|
||||||
|
|
||||||
/* This is a silly duplicate of the function in main.c to enable this source
|
|
||||||
to compile stand-alone for better debugging */
|
|
||||||
static void GetStr(char **string,
|
|
||||||
const char *value)
|
|
||||||
{
|
|
||||||
if(*string)
|
|
||||||
free(*string);
|
|
||||||
*string = strdup(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
*
|
|
||||||
* FormParse()
|
|
||||||
*
|
|
||||||
* Reads a 'name=value' paramter and builds the appropriate linked list.
|
|
||||||
*
|
|
||||||
* Specify files to upload with 'name=@filename'. Supports specified
|
|
||||||
* given Content-Type of the files. Such as ';type=<content-type>'.
|
|
||||||
*
|
|
||||||
* You may specify more than one file for a single name (field). Specify
|
|
||||||
* multiple files by writing it like:
|
|
||||||
*
|
|
||||||
* 'name=@filename,filename2,filename3'
|
|
||||||
*
|
|
||||||
* If you want content-types specified for each too, write them like:
|
|
||||||
*
|
|
||||||
* 'name=@filename;type=image/gif,filename2,filename3'
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#define FORM_FILE_SEPARATOR ','
|
#define FORM_FILE_SEPARATOR ','
|
||||||
#define FORM_TYPE_SEPARATOR ';'
|
#define FORM_TYPE_SEPARATOR ';'
|
||||||
|
|
||||||
static
|
|
||||||
int FormParse(char *input,
|
|
||||||
struct curl_httppost **httppost,
|
|
||||||
struct curl_httppost **last_post)
|
|
||||||
{
|
|
||||||
/* 'input' MUST be a string in the format 'name=contents' and we'll
|
|
||||||
build a linked list with the info */
|
|
||||||
char name[256];
|
|
||||||
char *contents;
|
|
||||||
char major[128];
|
|
||||||
char minor[128];
|
|
||||||
long flags = 0;
|
|
||||||
char *contp;
|
|
||||||
const char *type = NULL;
|
|
||||||
char *prevtype = NULL;
|
|
||||||
char *sep;
|
|
||||||
char *sep2;
|
|
||||||
struct curl_httppost *post;
|
|
||||||
struct curl_httppost *subpost; /* a sub-node */
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Preallocate contents to the length of input to make sure we don't
|
|
||||||
overwrite anything. */
|
|
||||||
contents = malloc(strlen(input));
|
|
||||||
contents[0] = '\000';
|
|
||||||
|
|
||||||
if(1 <= sscanf(input, "%255[^=]=%[^\n]", name, contents)) {
|
|
||||||
/* the input was using the correct format */
|
|
||||||
contp = contents;
|
|
||||||
|
|
||||||
if('@' == contp[0]) {
|
|
||||||
/* we use the @-letter to indicate file name(s) */
|
|
||||||
|
|
||||||
flags = HTTPPOST_FILENAME;
|
|
||||||
contp++;
|
|
||||||
|
|
||||||
post=NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
/* since this was a file, it may have a content-type specifier
|
|
||||||
at the end too */
|
|
||||||
|
|
||||||
sep=strchr(contp, FORM_TYPE_SEPARATOR);
|
|
||||||
sep2=strchr(contp, FORM_FILE_SEPARATOR);
|
|
||||||
|
|
||||||
/* pick the closest */
|
|
||||||
if(sep2 && (sep2 < sep)) {
|
|
||||||
sep = sep2;
|
|
||||||
|
|
||||||
/* no type was specified! */
|
|
||||||
}
|
|
||||||
if(sep) {
|
|
||||||
|
|
||||||
/* if we got here on a comma, don't do much */
|
|
||||||
if(FORM_FILE_SEPARATOR != *sep)
|
|
||||||
type = strstr(sep+1, "type=");
|
|
||||||
else
|
|
||||||
type=NULL;
|
|
||||||
|
|
||||||
*sep=0; /* terminate file name at separator */
|
|
||||||
|
|
||||||
if(type) {
|
|
||||||
type += strlen("type=");
|
|
||||||
|
|
||||||
if(2 != sscanf(type, "%127[^/]/%127[^,\n]",
|
|
||||||
major, minor)) {
|
|
||||||
free(contents);
|
|
||||||
return 2; /* illegal content-type syntax! */
|
|
||||||
}
|
|
||||||
/* now point beyond the content-type specifier */
|
|
||||||
sep = (char *)type + strlen(major)+strlen(minor)+1;
|
|
||||||
|
|
||||||
/* find the following comma */
|
|
||||||
sep=strchr(sep, FORM_FILE_SEPARATOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
type=NULL;
|
|
||||||
sep=strchr(contp, FORM_FILE_SEPARATOR);
|
|
||||||
}
|
|
||||||
if(sep) {
|
|
||||||
/* the next file name starts here */
|
|
||||||
*sep =0;
|
|
||||||
sep++;
|
|
||||||
}
|
|
||||||
if(!type) {
|
|
||||||
/*
|
|
||||||
* No type was specified, we scan through a few well-known
|
|
||||||
* extensions and pick the first we match!
|
|
||||||
*/
|
|
||||||
struct ContentType {
|
|
||||||
const char *extension;
|
|
||||||
const char *type;
|
|
||||||
};
|
|
||||||
static struct ContentType ctts[]={
|
|
||||||
{".gif", "image/gif"},
|
|
||||||
{".jpg", "image/jpeg"},
|
|
||||||
{".jpeg", "image/jpeg"},
|
|
||||||
{".txt", "text/plain"},
|
|
||||||
{".html", "text/html"}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(prevtype)
|
|
||||||
/* default to the previously set/used! */
|
|
||||||
type = prevtype;
|
|
||||||
else
|
|
||||||
/* It seems RFC1867 defines no Content-Type to default to
|
|
||||||
text/plain so we don't actually need to set this: */
|
|
||||||
type = HTTPPOST_CONTENTTYPE_DEFAULT;
|
|
||||||
|
|
||||||
for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
|
|
||||||
if(strlen(contp) >= strlen(ctts[i].extension)) {
|
|
||||||
if(strequal(contp +
|
|
||||||
strlen(contp) - strlen(ctts[i].extension),
|
|
||||||
ctts[i].extension)) {
|
|
||||||
type = ctts[i].type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* we have a type by now */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(NULL == post) {
|
|
||||||
/* For the first file name, we allocate and initiate the main list
|
|
||||||
node */
|
|
||||||
|
|
||||||
post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost));
|
|
||||||
if(post) {
|
|
||||||
memset(post, 0, sizeof(struct curl_httppost));
|
|
||||||
GetStr(&post->name, name); /* get the name */
|
|
||||||
GetStr(&post->contents, contp); /* get the contents */
|
|
||||||
post->contentslength = 0;
|
|
||||||
post->flags = flags;
|
|
||||||
if(type) {
|
|
||||||
GetStr(&post->contenttype, (char *)type); /* get type */
|
|
||||||
prevtype=post->contenttype; /* point to the allocated string! */
|
|
||||||
}
|
|
||||||
/* make the previous point to this */
|
|
||||||
if(*last_post)
|
|
||||||
(*last_post)->next = post;
|
|
||||||
else
|
|
||||||
(*httppost) = post;
|
|
||||||
|
|
||||||
(*last_post) = post;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* we add a file name to the previously allocated node, known as
|
|
||||||
'post' now */
|
|
||||||
subpost =(struct curl_httppost *)
|
|
||||||
malloc(sizeof(struct curl_httppost));
|
|
||||||
if(subpost) {
|
|
||||||
memset(subpost, 0, sizeof(struct curl_httppost));
|
|
||||||
GetStr(&subpost->name, name); /* get the name */
|
|
||||||
GetStr(&subpost->contents, contp); /* get the contents */
|
|
||||||
subpost->contentslength = 0;
|
|
||||||
subpost->flags = flags;
|
|
||||||
if(type) {
|
|
||||||
GetStr(&subpost->contenttype, (char *)type); /* get type */
|
|
||||||
prevtype=subpost->contenttype; /* point to allocated string! */
|
|
||||||
}
|
|
||||||
/* now, point our 'more' to the original 'more' */
|
|
||||||
subpost->more = post->more;
|
|
||||||
|
|
||||||
/* then move the original 'more' to point to ourselves */
|
|
||||||
post->more = subpost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contp = sep; /* move the contents pointer to after the separator */
|
|
||||||
} while(sep && *sep); /* loop if there's another file name */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost));
|
|
||||||
if(post) {
|
|
||||||
memset(post, 0, sizeof(struct curl_httppost));
|
|
||||||
GetStr(&post->name, name); /* get the name */
|
|
||||||
if( contp[0]=='<' ) {
|
|
||||||
GetStr(&post->contents, contp+1); /* get the contents */
|
|
||||||
post->contentslength = 0;
|
|
||||||
post->flags = HTTPPOST_READFILE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GetStr(&post->contents, contp); /* get the contents */
|
|
||||||
post->contentslength = 0;
|
|
||||||
post->flags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make the previous point to this */
|
|
||||||
if(*last_post)
|
|
||||||
(*last_post)->next = post;
|
|
||||||
else
|
|
||||||
(*httppost) = post;
|
|
||||||
|
|
||||||
(*last_post) = post;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
free(contents);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(contents);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int curl_formparse(char *input,
|
|
||||||
struct curl_httppost **httppost,
|
|
||||||
struct curl_httppost **last_post)
|
|
||||||
{
|
|
||||||
return FormParse(input, httppost, last_post);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
*
|
*
|
||||||
* AddHttpPost()
|
* AddHttpPost()
|
||||||
@@ -410,9 +152,8 @@ AddHttpPost(char * name, size_t namelength,
|
|||||||
struct curl_httppost **last_post)
|
struct curl_httppost **last_post)
|
||||||
{
|
{
|
||||||
struct curl_httppost *post;
|
struct curl_httppost *post;
|
||||||
post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost));
|
post = (struct curl_httppost *)calloc(sizeof(struct curl_httppost), 1);
|
||||||
if(post) {
|
if(post) {
|
||||||
memset(post, 0, sizeof(struct curl_httppost));
|
|
||||||
post->name = name;
|
post->name = name;
|
||||||
post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
|
post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
|
||||||
post->contents = value;
|
post->contents = value;
|
||||||
@@ -541,42 +282,45 @@ static const char * ContentTypeForFilename (const char *filename,
|
|||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
*
|
*
|
||||||
* AllocAndCopy()
|
* memdup()
|
||||||
*
|
*
|
||||||
* Copies the data currently available under *buffer using newly allocated
|
* Copies the 'source' data to a newly allocated buffer buffer (that is
|
||||||
* buffer (that becomes *buffer). Uses buffer_length if not null, else
|
* returned). Uses buffer_length if not null, else uses strlen to determine
|
||||||
* uses strlen to determine the length of the buffer to be copied
|
* the length of the buffer to be copied
|
||||||
*
|
*
|
||||||
* Returns 0 on success and 1 if the malloc failed.
|
* Returns the new pointer or NULL on failure.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static int AllocAndCopy(char **buffer, size_t buffer_length)
|
static char *memdup(const char *src, size_t buffer_length)
|
||||||
{
|
{
|
||||||
const char *src = *buffer;
|
|
||||||
size_t length;
|
size_t length;
|
||||||
bool add = FALSE;
|
bool add = FALSE;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
if (buffer_length)
|
if (buffer_length)
|
||||||
length = buffer_length;
|
length = buffer_length;
|
||||||
else {
|
else {
|
||||||
length = strlen(*buffer);
|
length = strlen(src);
|
||||||
add = TRUE;
|
add = TRUE;
|
||||||
}
|
}
|
||||||
*buffer = (char*)malloc(length+add);
|
buffer = (char*)malloc(length+add);
|
||||||
if (!*buffer)
|
if (!buffer)
|
||||||
return 1;
|
return NULL; /* fail */
|
||||||
memcpy(*buffer, src, length);
|
|
||||||
|
memcpy(buffer, src, length);
|
||||||
|
|
||||||
/* if length unknown do null termination */
|
/* if length unknown do null termination */
|
||||||
if (add)
|
if (add)
|
||||||
(*buffer)[length] = '\0';
|
buffer[length] = '\0';
|
||||||
return 0;
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
*
|
*
|
||||||
* FormAdd()
|
* FormAdd()
|
||||||
*
|
*
|
||||||
* Stores a 'name=value' formpost parameter and builds the appropriate
|
* Stores a formpost parameter and builds the appropriate linked list.
|
||||||
* linked list.
|
|
||||||
*
|
*
|
||||||
* Has two principal functionalities: using files and byte arrays as
|
* Has two principal functionalities: using files and byte arrays as
|
||||||
* post parts. Byte arrays are either copied or just the pointer is stored
|
* post parts. Byte arrays are either copied or just the pointer is stored
|
||||||
@@ -626,7 +370,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
struct curl_httppost **last_post,
|
struct curl_httppost **last_post,
|
||||||
va_list params)
|
va_list params)
|
||||||
{
|
{
|
||||||
FormInfo *first_form, *current_form, *form;
|
FormInfo *first_form, *current_form, *form = NULL;
|
||||||
CURLFORMcode return_value = CURL_FORMADD_OK;
|
CURLFORMcode return_value = CURL_FORMADD_OK;
|
||||||
const char *prevtype = NULL;
|
const char *prevtype = NULL;
|
||||||
struct curl_httppost *post = NULL;
|
struct curl_httppost *post = NULL;
|
||||||
@@ -642,22 +386,16 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
/*
|
/*
|
||||||
* We need to allocate the first struct to fill in.
|
* We need to allocate the first struct to fill in.
|
||||||
*/
|
*/
|
||||||
first_form = (FormInfo *)malloc(sizeof(struct FormInfo));
|
first_form = (FormInfo *)calloc(sizeof(struct FormInfo), 1);
|
||||||
if(first_form) {
|
if(!first_form)
|
||||||
memset(first_form, 0, sizeof(FormInfo));
|
|
||||||
current_form = first_form;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return CURL_FORMADD_MEMORY;
|
return CURL_FORMADD_MEMORY;
|
||||||
|
|
||||||
/*
|
current_form = first_form;
|
||||||
* Loop through all the options set.
|
|
||||||
*/
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
/* break if we have an error to report */
|
/*
|
||||||
if (return_value != CURL_FORMADD_OK)
|
* Loop through all the options set. Break if we have an error to report.
|
||||||
break;
|
*/
|
||||||
|
while (return_value == CURL_FORMADD_OK) {
|
||||||
|
|
||||||
/* first see if we have more parts of the array param */
|
/* first see if we have more parts of the array param */
|
||||||
if ( array_state ) {
|
if ( array_state ) {
|
||||||
@@ -752,7 +490,12 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
array_value:va_arg(params, char *);
|
array_value:va_arg(params, char *);
|
||||||
if (filename) {
|
if (filename) {
|
||||||
current_form->value = strdup(filename);
|
current_form->value = strdup(filename);
|
||||||
current_form->flags |= HTTPPOST_READFILE;
|
if(!current_form->value)
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
else {
|
||||||
|
current_form->flags |= HTTPPOST_READFILE;
|
||||||
|
current_form->value_alloc = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return_value = CURL_FORMADD_NULL;
|
return_value = CURL_FORMADD_NULL;
|
||||||
@@ -779,11 +522,17 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (filename)
|
if (filename) {
|
||||||
current_form->value = strdup(filename);
|
current_form->value = strdup(filename);
|
||||||
|
if(!current_form->value)
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
else {
|
||||||
|
current_form->flags |= HTTPPOST_FILENAME;
|
||||||
|
current_form->value_alloc = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return_value = CURL_FORMADD_NULL;
|
return_value = CURL_FORMADD_NULL;
|
||||||
current_form->flags |= HTTPPOST_FILENAME;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -807,8 +556,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (filename)
|
if (filename) {
|
||||||
current_form->value = strdup(filename);
|
current_form->value = strdup(filename);
|
||||||
|
if(!current_form->value)
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return_value = CURL_FORMADD_NULL;
|
return_value = CURL_FORMADD_NULL;
|
||||||
current_form->flags |= HTTPPOST_BUFFER;
|
current_form->flags |= HTTPPOST_BUFFER;
|
||||||
@@ -857,8 +609,13 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (contenttype)
|
if (contenttype) {
|
||||||
current_form->contenttype = strdup(contenttype);
|
current_form->contenttype = strdup(contenttype);
|
||||||
|
if(!current_form->contenttype)
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
else
|
||||||
|
current_form->contenttype_alloc = TRUE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return_value = CURL_FORMADD_NULL;
|
return_value = CURL_FORMADD_NULL;
|
||||||
}
|
}
|
||||||
@@ -885,8 +642,13 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
va_arg(params, char *);
|
va_arg(params, char *);
|
||||||
if( current_form->showfilename )
|
if( current_form->showfilename )
|
||||||
return_value = CURL_FORMADD_OPTION_TWICE;
|
return_value = CURL_FORMADD_OPTION_TWICE;
|
||||||
else
|
else {
|
||||||
current_form->showfilename = strdup(filename);
|
current_form->showfilename = strdup(filename);
|
||||||
|
if(!current_form->showfilename)
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
else
|
||||||
|
current_form->showfilename_alloc = TRUE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -925,25 +687,33 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
/* our contenttype is missing */
|
/* our contenttype is missing */
|
||||||
form->contenttype
|
form->contenttype
|
||||||
= strdup(ContentTypeForFilename(form->value, prevtype));
|
= strdup(ContentTypeForFilename(form->value, prevtype));
|
||||||
|
if(!form->contenttype) {
|
||||||
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
form->contenttype_alloc = TRUE;
|
||||||
}
|
}
|
||||||
if ( !(form->flags & HTTPPOST_PTRNAME) &&
|
if ( !(form->flags & HTTPPOST_PTRNAME) &&
|
||||||
(form == first_form) ) {
|
(form == first_form) ) {
|
||||||
/* copy name (without strdup; possibly contains null characters) */
|
/* copy name (without strdup; possibly contains null characters) */
|
||||||
if (AllocAndCopy(&form->name, form->namelength)) {
|
form->name = memdup(form->name, form->namelength);
|
||||||
|
if (!form->name) {
|
||||||
return_value = CURL_FORMADD_MEMORY;
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
form->name_alloc = TRUE;
|
||||||
}
|
}
|
||||||
if ( !(form->flags & HTTPPOST_FILENAME) &&
|
if ( !(form->flags & HTTPPOST_FILENAME) &&
|
||||||
!(form->flags & HTTPPOST_READFILE) &&
|
!(form->flags & HTTPPOST_READFILE) &&
|
||||||
!(form->flags & HTTPPOST_PTRCONTENTS) &&
|
!(form->flags & HTTPPOST_PTRCONTENTS) &&
|
||||||
!(form->flags & HTTPPOST_PTRBUFFER) ) {
|
!(form->flags & HTTPPOST_PTRBUFFER) ) {
|
||||||
|
|
||||||
/* copy value (without strdup; possibly contains null characters) */
|
/* copy value (without strdup; possibly contains null characters) */
|
||||||
if (AllocAndCopy(&form->value, form->contentslength)) {
|
form->value = memdup(form->value, form->contentslength);
|
||||||
|
if (!form->value) {
|
||||||
return_value = CURL_FORMADD_MEMORY;
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
form->value_alloc = TRUE;
|
||||||
}
|
}
|
||||||
post = AddHttpPost(form->name, form->namelength,
|
post = AddHttpPost(form->name, form->namelength,
|
||||||
form->value, form->contentslength,
|
form->value, form->contentslength,
|
||||||
@@ -953,8 +723,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
post, httppost,
|
post, httppost,
|
||||||
last_post);
|
last_post);
|
||||||
|
|
||||||
if(!post)
|
if(!post) {
|
||||||
return_value = CURL_FORMADD_MEMORY;
|
return_value = CURL_FORMADD_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (form->contenttype)
|
if (form->contenttype)
|
||||||
prevtype = form->contenttype;
|
prevtype = form->contenttype;
|
||||||
@@ -962,6 +734,22 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(return_value) {
|
||||||
|
/* we return on error, free possibly allocated fields */
|
||||||
|
if(!form)
|
||||||
|
form = current_form;
|
||||||
|
if(form) {
|
||||||
|
if(form->name_alloc)
|
||||||
|
free(form->name);
|
||||||
|
if(form->value_alloc)
|
||||||
|
free(form->value);
|
||||||
|
if(form->contenttype_alloc)
|
||||||
|
free(form->contenttype);
|
||||||
|
if(form->showfilename_alloc)
|
||||||
|
free(form->showfilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* always delete the allocated memory before returning */
|
/* always delete the allocated memory before returning */
|
||||||
form = first_form;
|
form = first_form;
|
||||||
while (form != NULL) {
|
while (form != NULL) {
|
||||||
@@ -993,13 +781,18 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* AddFormData() adds a chunk of data to the FormData linked list.
|
* AddFormData() adds a chunk of data to the FormData linked list.
|
||||||
|
*
|
||||||
|
* size is incremented by the chunk length, unless it is NULL
|
||||||
*/
|
*/
|
||||||
static size_t AddFormData(struct FormData **formp,
|
static CURLcode AddFormData(struct FormData **formp,
|
||||||
const void *line,
|
const void *line,
|
||||||
size_t length)
|
size_t length,
|
||||||
|
size_t *size)
|
||||||
{
|
{
|
||||||
struct FormData *newform = (struct FormData *)
|
struct FormData *newform = (struct FormData *)
|
||||||
malloc(sizeof(struct FormData));
|
malloc(sizeof(struct FormData));
|
||||||
|
if (!newform)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
newform->next = NULL;
|
newform->next = NULL;
|
||||||
|
|
||||||
/* we make it easier for plain strings: */
|
/* we make it easier for plain strings: */
|
||||||
@@ -1007,6 +800,10 @@ static size_t AddFormData(struct FormData **formp,
|
|||||||
length = strlen((char *)line);
|
length = strlen((char *)line);
|
||||||
|
|
||||||
newform->line = (char *)malloc(length+1);
|
newform->line = (char *)malloc(length+1);
|
||||||
|
if (!newform->line) {
|
||||||
|
free(newform);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
memcpy(newform->line, line, length);
|
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 */
|
||||||
@@ -1018,15 +815,18 @@ static size_t AddFormData(struct FormData **formp,
|
|||||||
else
|
else
|
||||||
*formp = newform;
|
*formp = newform;
|
||||||
|
|
||||||
return length;
|
if (size)
|
||||||
|
*size += length;
|
||||||
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AddFormDataf() adds printf()-style formatted data to the formdata chain.
|
* AddFormDataf() adds printf()-style formatted data to the formdata chain.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static size_t AddFormDataf(struct FormData **formp,
|
static CURLcode AddFormDataf(struct FormData **formp,
|
||||||
const char *fmt, ...)
|
size_t *size,
|
||||||
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char s[4096];
|
char s[4096];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -1034,7 +834,7 @@ static size_t AddFormDataf(struct FormData **formp,
|
|||||||
vsprintf(s, fmt, ap);
|
vsprintf(s, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return AddFormData(formp, s, 0);
|
return AddFormData(formp, s, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1077,6 +877,9 @@ void Curl_formclean(struct FormData *form)
|
|||||||
{
|
{
|
||||||
struct FormData *next;
|
struct FormData *next;
|
||||||
|
|
||||||
|
if(!form)
|
||||||
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
next=form->next; /* the following form line */
|
next=form->next; /* the following form line */
|
||||||
free(form->line); /* free the line */
|
free(form->line); /* free the line */
|
||||||
@@ -1144,30 +947,48 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
return result; /* no input => no output! */
|
return result; /* no input => no output! */
|
||||||
|
|
||||||
boundary = Curl_FormBoundary();
|
boundary = Curl_FormBoundary();
|
||||||
|
if(!boundary)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* Make the first line of the output */
|
/* Make the first line of the output */
|
||||||
AddFormDataf(&form,
|
result = AddFormDataf(&form, NULL,
|
||||||
"Content-Type: multipart/form-data;"
|
"Content-Type: multipart/form-data;"
|
||||||
" boundary=%s\r\n",
|
" boundary=%s\r\n",
|
||||||
boundary);
|
boundary);
|
||||||
/* we DO NOT count that line since that'll be part of the header! */
|
if (result) {
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* we DO NOT include that line in the total size of the POST, since it'll be
|
||||||
|
part of the header! */
|
||||||
|
|
||||||
firstform = form;
|
firstform = form;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
if(size)
|
if(size) {
|
||||||
size += AddFormDataf(&form, "\r\n");
|
result = AddFormDataf(&form, &size, "\r\n");
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* boundary */
|
/* boundary */
|
||||||
size += AddFormDataf(&form, "--%s\r\n", boundary);
|
result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
|
||||||
size += AddFormData(&form,
|
result = AddFormData(&form,
|
||||||
"Content-Disposition: form-data; name=\"", 0);
|
"Content-Disposition: form-data; name=\"", 0, &size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
|
||||||
size += AddFormData(&form, post->name, post->namelength);
|
result = AddFormData(&form, post->name, post->namelength, &size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
|
||||||
size += AddFormData(&form, "\"", 0);
|
result = AddFormData(&form, "\"", 0, &size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
|
||||||
if(post->more) {
|
if(post->more) {
|
||||||
/* If used, this is a link to more file names, we must then do
|
/* If used, this is a link to more file names, we must then do
|
||||||
@@ -1175,10 +996,12 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
|
|
||||||
fileboundary = Curl_FormBoundary();
|
fileboundary = Curl_FormBoundary();
|
||||||
|
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"\r\nContent-Type: multipart/mixed,"
|
"\r\nContent-Type: multipart/mixed,"
|
||||||
" boundary=%s\r\n",
|
" boundary=%s\r\n",
|
||||||
fileboundary);
|
fileboundary);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = post;
|
file = post;
|
||||||
@@ -1191,35 +1014,48 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
|
|
||||||
if(post->more) {
|
if(post->more) {
|
||||||
/* if multiple-file */
|
/* if multiple-file */
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"\r\n--%s\r\nContent-Disposition: "
|
"\r\n--%s\r\nContent-Disposition: "
|
||||||
"attachment; filename=\"%s\"",
|
"attachment; filename=\"%s\"",
|
||||||
fileboundary,
|
fileboundary,
|
||||||
(file->showfilename?file->showfilename:
|
(file->showfilename?file->showfilename:
|
||||||
file->contents));
|
file->contents));
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if((post->flags & HTTPPOST_FILENAME) ||
|
else if((post->flags & HTTPPOST_FILENAME) ||
|
||||||
(post->flags & HTTPPOST_BUFFER)) {
|
(post->flags & HTTPPOST_BUFFER)) {
|
||||||
|
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"; filename=\"%s\"",
|
"; filename=\"%s\"",
|
||||||
(post->showfilename?post->showfilename:
|
(post->showfilename?post->showfilename:
|
||||||
post->contents));
|
post->contents));
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file->contenttype) {
|
if(file->contenttype) {
|
||||||
/* we have a specified type */
|
/* we have a specified type */
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"\r\nContent-Type: %s",
|
"\r\nContent-Type: %s",
|
||||||
file->contenttype);
|
file->contenttype);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
curList = file->contentheader;
|
curList = file->contentheader;
|
||||||
while( curList ) {
|
while( curList ) {
|
||||||
/* Process the additional headers specified for this form */
|
/* Process the additional headers specified for this form */
|
||||||
size += AddFormDataf( &form, "\r\n%s", curList->data );
|
result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
curList = curList->next;
|
curList = curList->next;
|
||||||
}
|
}
|
||||||
|
if (result) {
|
||||||
|
Curl_formclean(firstform);
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* The header Content-Transfer-Encoding: seems to confuse some receivers
|
/* The header Content-Transfer-Encoding: seems to confuse some receivers
|
||||||
@@ -1235,7 +1071,9 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size += AddFormData(&form, "\r\n\r\n", 0);
|
result = AddFormData(&form, "\r\n\r\n", 0, &size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
|
||||||
if((post->flags & HTTPPOST_FILENAME) ||
|
if((post->flags & HTTPPOST_FILENAME) ||
|
||||||
(post->flags & HTTPPOST_READFILE)) {
|
(post->flags & HTTPPOST_READFILE)) {
|
||||||
@@ -1253,11 +1091,19 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if(fileread) {
|
if(fileread) {
|
||||||
while((nread = fread(buffer, 1, 1024, fileread)))
|
while((nread = fread(buffer, 1, 1024, fileread))) {
|
||||||
size += AddFormData(&form, buffer, nread);
|
result = AddFormData(&form, buffer, nread, &size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(fileread != stdin)
|
if(fileread != stdin)
|
||||||
fclose(fileread);
|
fclose(fileread);
|
||||||
|
if (result) {
|
||||||
|
Curl_formclean(firstform);
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Curl_formclean(firstform);
|
Curl_formclean(firstform);
|
||||||
@@ -1268,31 +1114,54 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if (post->flags & HTTPPOST_BUFFER) {
|
else if (post->flags & HTTPPOST_BUFFER) {
|
||||||
/* include contents of buffer */
|
/* include contents of buffer */
|
||||||
size += AddFormData(&form, post->buffer, post->bufferlength);
|
result = AddFormData(&form, post->buffer, post->bufferlength,
|
||||||
|
&size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
/* include the contents we got */
|
/* include the contents we got */
|
||||||
size += AddFormData(&form, post->contents, post->contentslength);
|
result = AddFormData(&form, post->contents, post->contentslength,
|
||||||
|
&size);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while((file = file->more)); /* for each specified file for this field */
|
} while((file = file->more)); /* for each specified file for this field */
|
||||||
|
if (result) {
|
||||||
|
Curl_formclean(firstform);
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if(post->more) {
|
if(post->more) {
|
||||||
/* this was a multiple-file inclusion, make a termination file
|
/* this was a multiple-file inclusion, make a termination file
|
||||||
boundary: */
|
boundary: */
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"\r\n--%s--",
|
"\r\n--%s--",
|
||||||
fileboundary);
|
fileboundary);
|
||||||
free(fileboundary);
|
free(fileboundary);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while((post=post->next)); /* for each field */
|
} while((post=post->next)); /* for each field */
|
||||||
|
if (result) {
|
||||||
|
Curl_formclean(firstform);
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* end-boundary for everything */
|
/* end-boundary for everything */
|
||||||
size += AddFormDataf(&form,
|
result = AddFormDataf(&form, &size,
|
||||||
"\r\n--%s--\r\n",
|
"\r\n--%s--\r\n",
|
||||||
boundary);
|
boundary);
|
||||||
|
if (result) {
|
||||||
|
Curl_formclean(firstform);
|
||||||
|
free(boundary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
*sizep = size;
|
*sizep = size;
|
||||||
|
|
||||||
|
|||||||
@@ -39,15 +39,19 @@ struct Form {
|
|||||||
/* used by FormAdd for temporary storage */
|
/* used by FormAdd for temporary storage */
|
||||||
typedef struct FormInfo {
|
typedef struct FormInfo {
|
||||||
char *name;
|
char *name;
|
||||||
|
bool name_alloc;
|
||||||
size_t namelength;
|
size_t namelength;
|
||||||
char *value;
|
char *value;
|
||||||
|
bool value_alloc;
|
||||||
size_t contentslength;
|
size_t contentslength;
|
||||||
char *contenttype;
|
char *contenttype;
|
||||||
|
bool contenttype_alloc;
|
||||||
long flags;
|
long flags;
|
||||||
char *buffer; /* pointer to existing buffer used for file upload */
|
char *buffer; /* pointer to existing buffer used for file upload */
|
||||||
size_t bufferlength;
|
size_t bufferlength;
|
||||||
char *showfilename; /* The file name to show. If not set, the actual
|
char *showfilename; /* The file name to show. If not set, the actual
|
||||||
file name will be used */
|
file name will be used */
|
||||||
|
bool showfilename_alloc;
|
||||||
struct curl_slist* contentheader;
|
struct curl_slist* contentheader;
|
||||||
struct FormInfo *more;
|
struct FormInfo *more;
|
||||||
} FormInfo;
|
} FormInfo;
|
||||||
|
|||||||
52
lib/ftp.c
52
lib/ftp.c
@@ -92,6 +92,7 @@
|
|||||||
#include "ssluse.h"
|
#include "ssluse.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "strerror.h"
|
#include "strerror.h"
|
||||||
|
#include "memory.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"
|
||||||
@@ -486,10 +487,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
|||||||
ftp->passwd = conn->passwd;
|
ftp->passwd = conn->passwd;
|
||||||
ftp->response_time = 3600; /* set default response time-out */
|
ftp->response_time = 3600; /* set default response time-out */
|
||||||
|
|
||||||
if (data->set.tunnel_thru_httpproxy) {
|
if (conn->bits.tunnel_proxy) {
|
||||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||||
result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET,
|
result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET,
|
||||||
conn->hostname, conn->remote_port);
|
conn->host.name, conn->remote_port);
|
||||||
if(CURLE_OK != result)
|
if(CURLE_OK != result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -737,13 +738,14 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
|||||||
*
|
*
|
||||||
* Input argument is already checked for validity.
|
* Input argument is already checked for validity.
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_ftp_done(struct connectdata *conn)
|
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct FTP *ftp = conn->proto.ftp;
|
struct FTP *ftp = conn->proto.ftp;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int ftpcode;
|
int ftpcode;
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
|
|
||||||
bool was_ctl_valid = ftp->ctl_valid;
|
bool was_ctl_valid = ftp->ctl_valid;
|
||||||
|
|
||||||
/* free the dir tree and file parts */
|
/* free the dir tree and file parts */
|
||||||
@@ -783,8 +785,24 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
|||||||
result = CURLE_FTP_COULDNT_RETR_FILE;
|
result = CURLE_FTP_COULDNT_RETR_FILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ftp->ctl_valid = was_ctl_valid;
|
switch(status) {
|
||||||
|
case CURLE_BAD_DOWNLOAD_RESUME:
|
||||||
|
case CURLE_FTP_WEIRD_PASV_REPLY:
|
||||||
|
case CURLE_FTP_PORT_FAILED:
|
||||||
|
case CURLE_FTP_COULDNT_SET_BINARY:
|
||||||
|
case CURLE_FTP_COULDNT_RETR_FILE:
|
||||||
|
case CURLE_FTP_ACCESS_DENIED:
|
||||||
|
/* the connection stays alive fine even though this happened */
|
||||||
|
/* fall-through */
|
||||||
|
case CURLE_OK: /* doesn't affect the control connection's status */
|
||||||
|
ftp->ctl_valid = was_ctl_valid;
|
||||||
|
break;
|
||||||
|
default: /* by default, an error means the control connection is
|
||||||
|
wedged and should not be used anymore */
|
||||||
|
ftp->ctl_valid = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#ifdef HAVE_KRB4
|
||||||
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
@@ -793,12 +811,12 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
|||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
sclose(conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
if(!ftp->no_transfer) {
|
if(!ftp->no_transfer && !status) {
|
||||||
/* Let's see what the server says about the transfer we just performed,
|
/* Let's see what the server says about the transfer we just performed,
|
||||||
but lower the timeout as sometimes this connection has died while
|
* but lower the timeout as sometimes this connection has died while the
|
||||||
the data has been transfered. This happens when doing through NATs
|
* data has been transfered. This happens when doing through NATs etc that
|
||||||
etc that abandon old silent connections.
|
* abandon old silent connections.
|
||||||
*/
|
*/
|
||||||
ftp->response_time = 60; /* give it only a minute for now */
|
ftp->response_time = 60; /* give it only a minute for now */
|
||||||
|
|
||||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||||
@@ -1367,14 +1385,14 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
if((in == CURL_INADDR_NONE) &&
|
if((in == CURL_INADDR_NONE) &&
|
||||||
Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
|
Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
|
||||||
rc = Curl_resolv(conn, myhost, 0, &h);
|
rc = Curl_resolv(conn, myhost, 0, &h);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
rc = Curl_wait_for_resolv(conn, &h);
|
rc = Curl_wait_for_resolv(conn, &h);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t len = strlen(data->set.ftpport);
|
size_t len = strlen(data->set.ftpport);
|
||||||
if(len>1) {
|
if(len>1) {
|
||||||
rc = Curl_resolv(conn, data->set.ftpport, 0, &h);
|
rc = Curl_resolv(conn, data->set.ftpport, 0, &h);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
rc = Curl_wait_for_resolv(conn, &h);
|
rc = Curl_wait_for_resolv(conn, &h);
|
||||||
}
|
}
|
||||||
if(h)
|
if(h)
|
||||||
@@ -1619,7 +1637,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
|||||||
newport = num;
|
newport = num;
|
||||||
|
|
||||||
/* we should use the same host we already are connected to */
|
/* we should use the same host we already are connected to */
|
||||||
newhostp = conn->hostname;
|
newhostp = conn->host.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1641,8 +1659,8 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
|||||||
* We don't want to rely on a former host lookup that might've expired
|
* We don't want to rely on a former host lookup that might've expired
|
||||||
* now, instead we remake the lookup here and now!
|
* now, instead we remake the lookup here and now!
|
||||||
*/
|
*/
|
||||||
rc = Curl_resolv(conn, conn->proxyhost, conn->port, &addr);
|
rc = Curl_resolv(conn, conn->proxy.name, conn->port, &addr);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
rc = Curl_wait_for_resolv(conn, &addr);
|
rc = Curl_wait_for_resolv(conn, &addr);
|
||||||
|
|
||||||
connectport =
|
connectport =
|
||||||
@@ -1652,7 +1670,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
|||||||
else {
|
else {
|
||||||
/* normal, direct, ftp connection */
|
/* normal, direct, ftp connection */
|
||||||
rc = Curl_resolv(conn, newhostp, newport, &addr);
|
rc = Curl_resolv(conn, newhostp, newport, &addr);
|
||||||
if(rc == 1)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
rc = Curl_wait_for_resolv(conn, &addr);
|
rc = Curl_wait_for_resolv(conn, &addr);
|
||||||
|
|
||||||
if(!addr) {
|
if(!addr) {
|
||||||
@@ -1684,7 +1702,7 @@ 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, newhostp, connectport);
|
ftp_pasv_verbose(conn, conninfo, newhostp, connectport);
|
||||||
|
|
||||||
if(data->set.tunnel_thru_httpproxy) {
|
if(conn->bits.tunnel_proxy) {
|
||||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||||
result = Curl_ConnectHTTPProxyTunnel(conn, SECONDARYSOCKET,
|
result = Curl_ConnectHTTPProxyTunnel(conn, SECONDARYSOCKET,
|
||||||
newhostp, newport);
|
newhostp, newport);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#ifndef CURL_DISABLE_FTP
|
#ifndef CURL_DISABLE_FTP
|
||||||
CURLcode Curl_ftp(struct connectdata *conn);
|
CURLcode Curl_ftp(struct connectdata *conn);
|
||||||
CURLcode Curl_ftp_done(struct connectdata *conn);
|
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
|
||||||
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);
|
||||||
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
|
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
|
||||||
|
|||||||
@@ -81,10 +81,9 @@
|
|||||||
# include <string.h>
|
# include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef MALLOCDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YYMAXDEPTH
|
#ifndef YYMAXDEPTH
|
||||||
#define YYMAXDEPTH 0
|
#define YYMAXDEPTH 0
|
||||||
|
|||||||
@@ -36,10 +36,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
static
|
static
|
||||||
char *GetEnv(const char *variable)
|
char *GetEnv(const char *variable)
|
||||||
|
|||||||
@@ -31,17 +31,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#ifdef VMS
|
#include "memory.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Make this the last #include */
|
/* Make this the last #include */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#else
|
|
||||||
#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
|
||||||
|
|||||||
30
lib/hash.c
30
lib/hash.c
@@ -28,12 +28,10 @@
|
|||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "llist.h"
|
#include "llist.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
|
||||||
/* this must be the last include file */
|
/* this must be the last include file */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
hash_str(const char *key, size_t key_length)
|
hash_str(const char *key, size_t key_length)
|
||||||
@@ -127,9 +125,17 @@ mk_hash_element(char *key, size_t key_len, const void *p)
|
|||||||
(curl_hash_element *) malloc(sizeof(curl_hash_element));
|
(curl_hash_element *) malloc(sizeof(curl_hash_element));
|
||||||
|
|
||||||
if(he) {
|
if(he) {
|
||||||
he->key = strdup(key);
|
char *dup = strdup(key);
|
||||||
he->key_len = key_len;
|
if(dup) {
|
||||||
he->ptr = (void *) p;
|
he->key = dup;
|
||||||
|
he->key_len = key_len;
|
||||||
|
he->ptr = (void *) p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* failed to duplicate the key, free memory and fail */
|
||||||
|
free(he);
|
||||||
|
he = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return he;
|
return he;
|
||||||
}
|
}
|
||||||
@@ -161,10 +167,16 @@ Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
|
|||||||
++h->size;
|
++h->size;
|
||||||
return p; /* return the new entry */
|
return p; /* return the new entry */
|
||||||
}
|
}
|
||||||
/* couldn't insert it, destroy the 'he' element again */
|
/*
|
||||||
hash_element_dtor(h, he);
|
* Couldn't insert it, destroy the 'he' element and the key again. We
|
||||||
|
* don't call hash_element_dtor() since that would also call the
|
||||||
|
* "destructor" for the actual data 'p'. When we fail, we shall not touch
|
||||||
|
* that data.
|
||||||
|
*/
|
||||||
|
free(he->key);
|
||||||
|
free(he);
|
||||||
}
|
}
|
||||||
h->dtor(p); /* remove the NEW entry */
|
|
||||||
return NULL; /* failure */
|
return NULL; /* failure */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
300
lib/hostares.c
Normal file
300
lib/hostares.c
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for ares-enabled builds
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifdef CURLRES_ARES
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_fdset() is called when someone from the outside world (using
|
||||||
|
* curl_multi_fdset()) wants to get our fd_set setup and we're talking with
|
||||||
|
* ares. The caller must make sure that this function is only called when we
|
||||||
|
* have a working ares channel.
|
||||||
|
*
|
||||||
|
* Returns: CURLE_OK always!
|
||||||
|
*/
|
||||||
|
|
||||||
|
CURLcode Curl_fdset(struct connectdata *conn,
|
||||||
|
fd_set *read_fd_set,
|
||||||
|
fd_set *write_fd_set,
|
||||||
|
int *max_fdp)
|
||||||
|
|
||||||
|
{
|
||||||
|
int max = ares_fds(conn->data->state.areschannel,
|
||||||
|
read_fd_set, write_fd_set);
|
||||||
|
*max_fdp = max;
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
|
||||||
|
* request has completed. It should also make sure to time-out if the
|
||||||
|
* operation seems to take too long.
|
||||||
|
*
|
||||||
|
* Returns normal CURLcode errors.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **dns)
|
||||||
|
{
|
||||||
|
fd_set read_fds, write_fds;
|
||||||
|
struct timeval tv={0,0};
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
int nfds;
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
FD_ZERO(&write_fds);
|
||||||
|
|
||||||
|
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
|
||||||
|
|
||||||
|
(void)select(nfds, &read_fds, &write_fds, NULL,
|
||||||
|
(struct timeval *)&tv);
|
||||||
|
|
||||||
|
/* Call ares_process() unconditonally here, even if we simply timed out
|
||||||
|
above, as otherwise the ares name resolve won't timeout! */
|
||||||
|
ares_process(data->state.areschannel, &read_fds, &write_fds);
|
||||||
|
|
||||||
|
*dns = NULL;
|
||||||
|
|
||||||
|
if(conn->async.done) {
|
||||||
|
/* we're done, kill the ares handle */
|
||||||
|
if(!conn->async.dns) {
|
||||||
|
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
|
||||||
|
ares_strerror(conn->async.status));
|
||||||
|
return CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
*dns = conn->async.dns;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_wait_for_resolv() waits for a resolve to finish. This function should
|
||||||
|
* be avoided since using this risk getting the multi interface to "hang".
|
||||||
|
*
|
||||||
|
* If 'entry' is non-NULL, make it point to the resolved dns entry
|
||||||
|
*
|
||||||
|
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
|
||||||
|
* CURLE_OPERATION_TIMEDOUT if a time-out occurred.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **entry)
|
||||||
|
{
|
||||||
|
CURLcode rc=CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
long timeout = CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
|
||||||
|
|
||||||
|
/* now, see if there's a connect timeout or a regular timeout to
|
||||||
|
use instead of the default one */
|
||||||
|
if(conn->data->set.connecttimeout)
|
||||||
|
timeout = conn->data->set.connecttimeout;
|
||||||
|
else if(conn->data->set.timeout)
|
||||||
|
timeout = conn->data->set.timeout;
|
||||||
|
|
||||||
|
/* We convert the number of seconds into number of milliseconds here: */
|
||||||
|
if(timeout < 2147483)
|
||||||
|
/* maximum amount of seconds that can be multiplied with 1000 and
|
||||||
|
still fit within 31 bits */
|
||||||
|
timeout *= 1000;
|
||||||
|
else
|
||||||
|
timeout = 0x7fffffff; /* ridiculous amount of time anyway */
|
||||||
|
|
||||||
|
/* Wait for the name resolve query to complete. */
|
||||||
|
while (1) {
|
||||||
|
int nfds=0;
|
||||||
|
fd_set read_fds, write_fds;
|
||||||
|
struct timeval *tvp, tv, store;
|
||||||
|
int count;
|
||||||
|
struct timeval now = Curl_tvnow();
|
||||||
|
long timediff;
|
||||||
|
|
||||||
|
store.tv_sec = (int)timeout/1000;
|
||||||
|
store.tv_usec = (timeout%1000)*1000;
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
FD_ZERO(&write_fds);
|
||||||
|
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
|
||||||
|
if (nfds == 0)
|
||||||
|
/* no file descriptors means we're done waiting */
|
||||||
|
break;
|
||||||
|
tvp = ares_timeout(data->state.areschannel, &store, &tv);
|
||||||
|
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
|
||||||
|
if (count < 0 && errno != EINVAL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ares_process(data->state.areschannel, &read_fds, &write_fds);
|
||||||
|
|
||||||
|
timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
|
||||||
|
timeout -= timediff?timediff:1; /* always deduct at least 1 */
|
||||||
|
if (timeout < 0) {
|
||||||
|
/* our timeout, so we cancel the ares operation */
|
||||||
|
ares_cancel(data->state.areschannel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Operation complete, if the lookup was successful we now have the entry
|
||||||
|
in the cache. */
|
||||||
|
|
||||||
|
if(entry)
|
||||||
|
*entry = conn->async.dns;
|
||||||
|
|
||||||
|
if(!conn->async.dns) {
|
||||||
|
/* a name was not resolved */
|
||||||
|
if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
|
||||||
|
failf(data, "Resolving host timed out: %s", conn->host.dispname);
|
||||||
|
rc = CURLE_OPERATION_TIMEDOUT;
|
||||||
|
}
|
||||||
|
else if(conn->async.done) {
|
||||||
|
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
|
||||||
|
ares_strerror(conn->async.status));
|
||||||
|
rc = CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = CURLE_OPERATION_TIMEDOUT;
|
||||||
|
|
||||||
|
/* close the connection, since we can't return failure here without
|
||||||
|
cleaning up this connection properly */
|
||||||
|
Curl_disconnect(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() - when using ares
|
||||||
|
*
|
||||||
|
* Returns name information about the given hostname and port number. If
|
||||||
|
* successful, the 'hostent' is returned and the forth argument will point to
|
||||||
|
* memory we need to free after use. That memory *MUST* be freed with
|
||||||
|
* Curl_freeaddrinfo(), nothing else.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp)
|
||||||
|
{
|
||||||
|
char *bufp;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
in_addr_t in = inet_addr(hostname);
|
||||||
|
|
||||||
|
*waitp = FALSE;
|
||||||
|
|
||||||
|
if (in != CURL_INADDR_NONE)
|
||||||
|
/* This is a dotted IP address 123.123.123.123-style */
|
||||||
|
return Curl_ip2addr(in, hostname);
|
||||||
|
|
||||||
|
bufp = strdup(hostname);
|
||||||
|
|
||||||
|
if(bufp) {
|
||||||
|
Curl_safefree(conn->async.hostname);
|
||||||
|
conn->async.hostname = bufp;
|
||||||
|
conn->async.port = port;
|
||||||
|
conn->async.done = FALSE; /* not done */
|
||||||
|
conn->async.status = 0; /* clear */
|
||||||
|
conn->async.dns = NULL; /* clear */
|
||||||
|
|
||||||
|
/* areschannel is already setup in the Curl_open() function */
|
||||||
|
ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
|
||||||
|
Curl_addrinfo_callback, conn);
|
||||||
|
|
||||||
|
*waitp = TRUE; /* please wait for the response */
|
||||||
|
}
|
||||||
|
return NULL; /* no struct yet */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CURLRES_ARES */
|
||||||
154
lib/hostasyn.c
Normal file
154
lib/hostasyn.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for builds using asynchronous name resolves
|
||||||
|
**********************************************************************/
|
||||||
|
#ifdef CURLRES_ASYNCH
|
||||||
|
/*
|
||||||
|
* Curl_addrinfo_callback() gets called by ares/gethostbyname_thread() when we
|
||||||
|
* got the name resolved (or not!).
|
||||||
|
*
|
||||||
|
* If the status argument is CURL_ASYNC_SUCCESS, we might need to copy the
|
||||||
|
* address field since it might be freed when this function returns. This
|
||||||
|
* operation stores the resolved data in the DNS cache.
|
||||||
|
*
|
||||||
|
* NOTE: for IPv6 operations, Curl_addrinfo_copy() returns the same
|
||||||
|
* pointer it is given as argument!
|
||||||
|
*
|
||||||
|
* The storage operation locks and unlocks the DNS cache.
|
||||||
|
*/
|
||||||
|
void Curl_addrinfo_callback(void *arg, /* "struct connectdata *" */
|
||||||
|
int status,
|
||||||
|
Curl_addrinfo *hostent)
|
||||||
|
{
|
||||||
|
struct connectdata *conn = (struct connectdata *)arg;
|
||||||
|
struct Curl_dns_entry *dns = NULL;
|
||||||
|
|
||||||
|
conn->async.done = TRUE;
|
||||||
|
conn->async.status = status;
|
||||||
|
|
||||||
|
if(CURL_ASYNC_SUCCESS == status) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IPv4: Curl_addrinfo_copy() copies the address and returns an allocated
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* IPv6: Curl_addrinfo_copy() returns the input pointer!
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *he = Curl_addrinfo_copy(hostent);
|
||||||
|
if(he) {
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
if(data->share)
|
||||||
|
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
|
dns = Curl_cache_addr(data, he,
|
||||||
|
conn->async.hostname,
|
||||||
|
conn->async.port);
|
||||||
|
if(!dns)
|
||||||
|
/* failed to store, cleanup and return error */
|
||||||
|
Curl_freeaddrinfo(he);
|
||||||
|
|
||||||
|
if(data->share)
|
||||||
|
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->async.dns = dns;
|
||||||
|
|
||||||
|
/* ipv4: The input hostent struct will be freed by ares when we return from
|
||||||
|
this function */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CURLRES_ASYNC */
|
||||||
1182
lib/hostip.c
1182
lib/hostip.c
File diff suppressed because it is too large
Load Diff
153
lib/hostip.h
153
lib/hostip.h
@@ -51,20 +51,42 @@ struct Curl_dns_entry {
|
|||||||
* The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
|
* The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
|
||||||
* use, or we'll leak memory!
|
* use, or we'll leak memory!
|
||||||
*/
|
*/
|
||||||
|
/* return codes */
|
||||||
|
#define CURLRESOLV_ERROR -1
|
||||||
|
#define CURLRESOLV_RESOLVED 0
|
||||||
|
#define CURLRESOLV_PENDING 1
|
||||||
|
int Curl_resolv(struct connectdata *conn, char *hostname,
|
||||||
|
int port, struct Curl_dns_entry **dnsentry);
|
||||||
|
|
||||||
int Curl_resolv(struct connectdata *conn,
|
/*
|
||||||
char *hostname,
|
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
|
||||||
int port,
|
* been set and returns TRUE if they are OK.
|
||||||
struct Curl_dns_entry **dnsentry);
|
*/
|
||||||
|
bool Curl_ipvalid(struct SessionHandle *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() is the generic low-level name resolve API within this
|
||||||
|
* source file. There are several versions of this function - for different
|
||||||
|
* name resolve layers (selected at build-time). They all take this same set
|
||||||
|
* of arguments
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp);
|
||||||
|
|
||||||
CURLcode Curl_is_resolved(struct connectdata *conn,
|
CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||||
struct Curl_dns_entry **dns);
|
struct Curl_dns_entry **dns);
|
||||||
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||||
struct Curl_dns_entry **dnsentry);
|
struct Curl_dns_entry **dnsentry);
|
||||||
CURLcode Curl_multi_ares_fdset(struct connectdata *conn,
|
|
||||||
fd_set *read_fd_set,
|
/* Curl_fdset() is a generic function that exists in multiple versions
|
||||||
fd_set *write_fd_set,
|
depending on what name resolve technology we've built to use. The function
|
||||||
int *max_fdp);
|
is called from the curl_multi_fdset() function */
|
||||||
|
CURLcode Curl_fdset(struct connectdata *conn,
|
||||||
|
fd_set *read_fd_set,
|
||||||
|
fd_set *write_fd_set,
|
||||||
|
int *max_fdp);
|
||||||
/* unlock a previously resolved dns entry */
|
/* unlock a previously resolved dns entry */
|
||||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
|
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
|
||||||
|
|
||||||
@@ -81,19 +103,124 @@ curl_hash *Curl_mk_dnscache(void);
|
|||||||
void Curl_hostcache_prune(struct SessionHandle *data);
|
void Curl_hostcache_prune(struct SessionHandle *data);
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
#ifdef CURLDEBUG
|
||||||
void curl_freeaddrinfo(struct addrinfo *freethis,
|
void curl_dofreeaddrinfo(struct addrinfo *freethis,
|
||||||
|
int line, const char *source);
|
||||||
|
int curl_dogetaddrinfo(char *hostname, char *service,
|
||||||
|
struct addrinfo *hints,
|
||||||
|
struct addrinfo **result,
|
||||||
|
int line, const char *source);
|
||||||
|
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||||
|
char *host, size_t hostlen,
|
||||||
|
char *serv, size_t servlen, int flags,
|
||||||
int line, const char *source);
|
int line, const char *source);
|
||||||
int curl_getaddrinfo(char *hostname, char *service,
|
|
||||||
struct addrinfo *hints,
|
|
||||||
struct addrinfo **result,
|
|
||||||
int line, const char *source);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* This is the callback function that is used when we build with asynch
|
||||||
|
resolve */
|
||||||
|
void Curl_addrinfo_callback(void *arg,
|
||||||
|
int status,
|
||||||
|
Curl_addrinfo *hostent);
|
||||||
|
|
||||||
|
/* This is a utility-function for ipv4-builds to create a hostent struct
|
||||||
|
from a numerical-only IP address */
|
||||||
|
Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname);
|
||||||
|
|
||||||
|
/* relocate a hostent struct */
|
||||||
|
void Curl_hostent_relocate(struct hostent *h, long offset);
|
||||||
|
|
||||||
|
/* copy a Curl_addrinfo struct, currently this only supports copying
|
||||||
|
a hostent (ipv4-style) struct */
|
||||||
|
Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *orig);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (IPv6) Curl_printable_address() returns a printable version of the
|
||||||
|
* ai->ai_addr address given in the 2nd argument. The first should be the
|
||||||
|
* ai->ai_family and the result will be stored in the buf that is bufsize
|
||||||
|
* bytes big.
|
||||||
|
*/
|
||||||
|
const char *Curl_printable_address(int af, void *addr,
|
||||||
|
char *buf, size_t bufsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
||||||
|
*
|
||||||
|
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
|
||||||
|
*/
|
||||||
|
struct Curl_dns_entry *
|
||||||
|
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
|
||||||
|
char *hostname, int port);
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define CURL_INADDR_NONE (in_addr_t) ~0
|
#define CURL_INADDR_NONE (in_addr_t) ~0
|
||||||
#else
|
#else
|
||||||
#define CURL_INADDR_NONE INADDR_NONE
|
#define CURL_INADDR_NONE INADDR_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup comfortable CURLRES_* defines to use in the host*.c sources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_ARES
|
||||||
|
#define CURLRES_ASYNCH
|
||||||
|
#define CURLRES_ARES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_THREADING_GETHOSTBYNAME
|
||||||
|
#define CURLRES_ASYNCH
|
||||||
|
#define CURLRES_THREADED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_THREADING_GETADDRINFO
|
||||||
|
#define CURLRES_ASYNCH
|
||||||
|
#define CURLRES_THREADED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
#define CURLRES_IPV6
|
||||||
|
#else
|
||||||
|
#define CURLRES_IPV4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CURLRES_IPV4
|
||||||
|
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(CURLRES_ASYNCH)
|
||||||
|
/* If built for ipv4 and missing gethostbyname_r(), or if using async name
|
||||||
|
resolve, we need the Curl_addrinfo_copy() function (which itself needs the
|
||||||
|
Curl_hostent_relocate() function)) */
|
||||||
|
#define CURLRES_ADDRINFO_COPY
|
||||||
|
#define CURLRES_HOSTENT_RELOCATE
|
||||||
|
#endif
|
||||||
|
#endif /* IPv4-only */
|
||||||
|
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME_R_6
|
||||||
|
#define CURLRES_HOSTENT_RELOCATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME_R_5
|
||||||
|
#define CURLRES_HOSTENT_RELOCATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CURLRES_ASYNCH
|
||||||
|
#define CURLRES_SYNCH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_LIBIDN
|
||||||
|
#define CURLRES_IDN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Allocate enough memory to hold the full name information structs and
|
||||||
|
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
||||||
|
* required for storing all possible aliases and IP numbers is according to
|
||||||
|
* Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes!
|
||||||
|
*/
|
||||||
|
#define CURL_HOSTENT_SIZE 9000
|
||||||
|
|
||||||
|
#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
|
||||||
|
many seconds for a name resolve */
|
||||||
|
|
||||||
|
#ifdef CURLRES_ARES
|
||||||
|
#define CURL_ASYNC_SUCCESS ARES_SUCCESS
|
||||||
|
#else
|
||||||
|
#define CURL_ASYNC_SUCCESS CURLE_OK
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
399
lib/hostip4.c
Normal file
399
lib/hostip4.c
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for plain-ipv4 builds
|
||||||
|
**********************************************************************/
|
||||||
|
#ifdef CURLRES_IPV4 /* plain ipv4 code coming up */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a wrapper function for freeing name information in a protocol
|
||||||
|
* independent way. This takes care of using the appropriate underlying
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
void Curl_freeaddrinfo(Curl_addrinfo *p)
|
||||||
|
{
|
||||||
|
free(p); /* works fine for the ARES case too */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
|
||||||
|
* been set and returns TRUE if they are OK.
|
||||||
|
*/
|
||||||
|
bool Curl_ipvalid(struct SessionHandle *data)
|
||||||
|
{
|
||||||
|
if(data->set.ip_version == CURL_IPRESOLVE_V6)
|
||||||
|
/* an ipv6 address was requested and we can't get/use one */
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE; /* OK, proceed */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_ip2addr() takes a 32bit ipv4 internet address as input parameter
|
||||||
|
* together with a pointer to the string version of the address, and it
|
||||||
|
* retruns a malloc()ed version of a hostent struct filled in correctly with
|
||||||
|
* information for this address/host.
|
||||||
|
*
|
||||||
|
* The input parameters ARE NOT checked for validity but they are expected
|
||||||
|
* to have been checked already when this is called.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname)
|
||||||
|
{
|
||||||
|
struct hostent *h;
|
||||||
|
struct in_addr *addrentry;
|
||||||
|
struct namebuf {
|
||||||
|
struct hostent hostentry;
|
||||||
|
char *h_addr_list[2];
|
||||||
|
struct in_addr addrentry;
|
||||||
|
char h_name[16]; /* 123.123.123.123 = 15 letters is maximum */
|
||||||
|
} *buf = (struct namebuf *)malloc(sizeof(struct namebuf));
|
||||||
|
|
||||||
|
if(!buf)
|
||||||
|
return NULL; /* major failure */
|
||||||
|
|
||||||
|
h = &buf->hostentry;
|
||||||
|
h->h_addr_list = &buf->h_addr_list[0];
|
||||||
|
addrentry = &buf->addrentry;
|
||||||
|
addrentry->s_addr = num;
|
||||||
|
h->h_addr_list[0] = (char*)addrentry;
|
||||||
|
h->h_addr_list[1] = NULL;
|
||||||
|
h->h_addrtype = AF_INET;
|
||||||
|
h->h_length = sizeof(*addrentry);
|
||||||
|
h->h_name = &buf->h_name[0];
|
||||||
|
h->h_aliases = NULL;
|
||||||
|
|
||||||
|
/* Now store the dotted version of the address */
|
||||||
|
snprintf(h->h_name, 16, "%s", hostname);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CURLRES_SYNCH /* the functions below are for synchronous resolves */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() - the ipv4 synchronous version.
|
||||||
|
*
|
||||||
|
* The original code to this function was once stolen from the Dancer source
|
||||||
|
* code, written by Bjorn Reese, it has since been patched and modified
|
||||||
|
* considerably.
|
||||||
|
*
|
||||||
|
* gethostbyname_r() is the thread-safe version of the gethostbyname()
|
||||||
|
* function. When we build for plain IPv4, we attempt to use this
|
||||||
|
* function. There are _three_ different gethostbyname_r() versions, and we
|
||||||
|
* detect which one this platform supports in the configure script and set up
|
||||||
|
* the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or
|
||||||
|
* HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME
|
||||||
|
* has the corresponding rules. This is primarily on *nix. Note that some unix
|
||||||
|
* flavours have thread-safe versions of the plain gethostbyname() etc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp)
|
||||||
|
{
|
||||||
|
struct hostent *h = NULL;
|
||||||
|
in_addr_t in;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
(void)port; /* unused in IPv4 code */
|
||||||
|
|
||||||
|
*waitp = 0; /* don't wait, we act synchronously */
|
||||||
|
|
||||||
|
in=inet_addr(hostname);
|
||||||
|
if (in != CURL_INADDR_NONE)
|
||||||
|
/* This is a dotted IP address 123.123.123.123-style */
|
||||||
|
return Curl_ip2addr(in, hostname);
|
||||||
|
|
||||||
|
#if defined(HAVE_GETHOSTBYNAME_R)
|
||||||
|
/*
|
||||||
|
* gethostbyname_r() is the preferred resolve function for many platforms.
|
||||||
|
* Since there are three different versions of it, the following code is
|
||||||
|
* somewhat #ifdef-ridden.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
int h_errnop;
|
||||||
|
int res=ERANGE;
|
||||||
|
int step_size=200;
|
||||||
|
int *buf = (int *)calloc(CURL_HOSTENT_SIZE, 1);
|
||||||
|
if(!buf)
|
||||||
|
return NULL; /* major failure */
|
||||||
|
/*
|
||||||
|
* The clearing of the buffer is a workaround for a gethostbyname_r bug in
|
||||||
|
* qnx nto and it is also _required_ for some of these functions on some
|
||||||
|
* platforms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME_R_5
|
||||||
|
/* Solaris, IRIX and more */
|
||||||
|
(void)res; /* prevent compiler warning */
|
||||||
|
while(!h) {
|
||||||
|
h = gethostbyname_r(hostname,
|
||||||
|
(struct hostent *)buf,
|
||||||
|
(char *)buf + sizeof(struct hostent),
|
||||||
|
step_size - sizeof(struct hostent),
|
||||||
|
&h_errnop);
|
||||||
|
|
||||||
|
/* If the buffer is too small, it returns NULL and sets errno to
|
||||||
|
* ERANGE. The errno is thread safe if this is compiled with
|
||||||
|
* -D_REENTRANT as then the 'errno' variable is a macro defined to get
|
||||||
|
* used properly for threads.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(h || (errno != ERANGE))
|
||||||
|
break;
|
||||||
|
|
||||||
|
step_size+=200;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CURLDEBUG
|
||||||
|
infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(h) {
|
||||||
|
int offset;
|
||||||
|
h=(struct hostent *)realloc(buf, step_size);
|
||||||
|
offset=(long)h-(long)buf;
|
||||||
|
Curl_hostent_relocate(h, offset);
|
||||||
|
buf=(int *)h;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* HAVE_GETHOSTBYNAME_R_5 */
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME_R_6
|
||||||
|
/* Linux */
|
||||||
|
do {
|
||||||
|
res=gethostbyname_r(hostname,
|
||||||
|
(struct hostent *)buf,
|
||||||
|
(char *)buf + sizeof(struct hostent),
|
||||||
|
step_size - sizeof(struct hostent),
|
||||||
|
&h, /* DIFFERENCE */
|
||||||
|
&h_errnop);
|
||||||
|
/* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
|
||||||
|
* sudden this function returns EAGAIN if the given buffer size is too
|
||||||
|
* small. Previous versions are known to return ERANGE for the same
|
||||||
|
* problem.
|
||||||
|
*
|
||||||
|
* This wouldn't be such a big problem if older versions wouldn't
|
||||||
|
* sometimes return EAGAIN on a common failure case. Alas, we can't
|
||||||
|
* assume that EAGAIN *or* ERANGE means ERANGE for any given version of
|
||||||
|
* glibc.
|
||||||
|
*
|
||||||
|
* For now, we do that and thus we may call the function repeatedly and
|
||||||
|
* fail for older glibc versions that return EAGAIN, until we run out of
|
||||||
|
* buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
|
||||||
|
*
|
||||||
|
* If anyone has a better fix, please tell us!
|
||||||
|
*
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* On October 23rd 2003, Dan C dug up more details on the mysteries of
|
||||||
|
* gethostbyname_r() in glibc:
|
||||||
|
*
|
||||||
|
* In glibc 2.2.5 the interface is different (this has also been
|
||||||
|
* discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
|
||||||
|
* explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
|
||||||
|
* (shipped/upgraded by Redhat 7.2) don't show this behavior!
|
||||||
|
*
|
||||||
|
* In this "buggy" version, the return code is -1 on error and 'errno'
|
||||||
|
* is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
|
||||||
|
* thread-safe variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(((ERANGE == res) || (EAGAIN == res)) ||
|
||||||
|
((res<0) && ((ERANGE == errno) || (EAGAIN == errno))))
|
||||||
|
step_size+=200;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} while(step_size <= CURL_HOSTENT_SIZE);
|
||||||
|
|
||||||
|
if(!h) /* failure */
|
||||||
|
res=1;
|
||||||
|
|
||||||
|
#ifdef CURLDEBUG
|
||||||
|
infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
|
||||||
|
#endif
|
||||||
|
if(!res) {
|
||||||
|
int offset;
|
||||||
|
h=(struct hostent *)realloc(buf, step_size);
|
||||||
|
offset=(long)h-(long)buf;
|
||||||
|
Curl_hostent_relocate(h, offset);
|
||||||
|
buf=(int *)h;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif/* HAVE_GETHOSTBYNAME_R_6 */
|
||||||
|
#ifdef HAVE_GETHOSTBYNAME_R_3
|
||||||
|
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
|
||||||
|
|
||||||
|
/* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
|
||||||
|
* the plain fact that it does not return unique full buffers on each
|
||||||
|
* call, but instead several of the pointers in the hostent structs will
|
||||||
|
* point to the same actual data! This have the unfortunate down-side that
|
||||||
|
* our caching system breaks down horribly. Luckily for us though, AIX 4.3
|
||||||
|
* and more recent versions have a "completely thread-safe"[*] libc where
|
||||||
|
* all the data is stored in thread-specific memory areas making calls to
|
||||||
|
* the plain old gethostbyname() work fine even for multi-threaded
|
||||||
|
* programs.
|
||||||
|
*
|
||||||
|
* This AIX 4.3 or later detection is all made in the configure script.
|
||||||
|
*
|
||||||
|
* Troels Walsted Hansen helped us work this out on March 3rd, 2003.
|
||||||
|
*
|
||||||
|
* [*] = much later we've found out that it isn't at all "completely
|
||||||
|
* thread-safe", but at least the gethostbyname() function is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(CURL_HOSTENT_SIZE >=
|
||||||
|
(sizeof(struct hostent)+sizeof(struct hostent_data))) {
|
||||||
|
|
||||||
|
/* August 22nd, 2000: Albert Chin-A-Young brought an updated version
|
||||||
|
* that should work! September 20: Richard Prescott worked on the buffer
|
||||||
|
* size dilemma.
|
||||||
|
*/
|
||||||
|
|
||||||
|
res = gethostbyname_r(hostname,
|
||||||
|
(struct hostent *)buf,
|
||||||
|
(struct hostent_data *)((char *)buf +
|
||||||
|
sizeof(struct hostent)));
|
||||||
|
h_errnop= errno; /* we don't deal with this, but set it anyway */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = -1; /* failure, too smallish buffer size */
|
||||||
|
|
||||||
|
if(!res) { /* success */
|
||||||
|
|
||||||
|
h = (struct hostent*)buf; /* result expected in h */
|
||||||
|
|
||||||
|
/* This is the worst kind of the different gethostbyname_r() interfaces.
|
||||||
|
* Since we don't know how big buffer this particular lookup required,
|
||||||
|
* we can't realloc down the huge alloc without doing closer analysis of
|
||||||
|
* the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
|
||||||
|
* name lookup. Fixing this would require an extra malloc() and then
|
||||||
|
* calling Curl_addrinfo_copy() that subsequent realloc()s down the new
|
||||||
|
* memory area to the actually used amount.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* HAVE_GETHOSTBYNAME_R_3 */
|
||||||
|
{
|
||||||
|
infof(data, "gethostbyname_r(2) failed for %s\n", hostname);
|
||||||
|
h = NULL; /* set return code to NULL */
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
#else /* HAVE_GETHOSTBYNAME_R */
|
||||||
|
/*
|
||||||
|
* Here is code for platforms that don't have gethostbyname_r() or for
|
||||||
|
* which the gethostbyname() is the preferred() function.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
h = gethostbyname(hostname);
|
||||||
|
if (!h)
|
||||||
|
infof(data, "gethostbyname(2) failed for %s\n", hostname);
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Copy the hostent struct right here, as the static one we got a
|
||||||
|
* pointer to might get removed when we don't want/expect that. Windows
|
||||||
|
* (other platforms?) also doesn't allow passing of the returned data
|
||||||
|
* between threads, which thus the copying here them allows the app to
|
||||||
|
* do.
|
||||||
|
*/
|
||||||
|
h = Curl_addrinfo_copy(h);
|
||||||
|
}
|
||||||
|
#endif /*HAVE_GETHOSTBYNAME_R */
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CURLRES_SYNCH */
|
||||||
|
|
||||||
|
#endif /* CURLRES_IPV4 */
|
||||||
283
lib/hostip6.c
Normal file
283
lib/hostip6.c
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for ipv6-enabled builds
|
||||||
|
**********************************************************************/
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
/*
|
||||||
|
* This is a wrapper function for freeing name information in a protocol
|
||||||
|
* independent way. This takes care of using the appropriate underlaying
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
void Curl_freeaddrinfo(Curl_addrinfo *p)
|
||||||
|
{
|
||||||
|
freeaddrinfo(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_printable_address() returns a printable version of the ai->ai_addr
|
||||||
|
* address given in the 2nd argument. The first should be the ai->ai_family
|
||||||
|
* and the result will be stored in the buf that is bufsize bytes big.
|
||||||
|
*
|
||||||
|
* If the conversion fails, it returns NULL.
|
||||||
|
*/
|
||||||
|
const char *Curl_printable_address(int af, void *addr,
|
||||||
|
char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
const struct in_addr *addr4 =
|
||||||
|
&((const struct sockaddr_in*)addr)->sin_addr;
|
||||||
|
const struct in6_addr *addr6 =
|
||||||
|
&((const struct sockaddr_in6*)addr)->sin6_addr;
|
||||||
|
return Curl_inet_ntop(af, af == AF_INET6 ?
|
||||||
|
(const void *)addr6 :
|
||||||
|
(const void *)addr4, buf, bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CURLRES_ASYNCH
|
||||||
|
/*
|
||||||
|
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
|
||||||
|
* address. But this is an ipv6 build and then we don't copy the address, we
|
||||||
|
* just return the same pointer!
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *source)
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CURLDEBUG
|
||||||
|
/* These are strictly for memory tracing and are using the same style as the
|
||||||
|
* family otherwise present in memdebug.c. I put these ones here since they
|
||||||
|
* require a bunch of structs I didn't wanna include in memdebug.c
|
||||||
|
*/
|
||||||
|
int curl_dogetaddrinfo(char *hostname, char *service,
|
||||||
|
struct addrinfo *hints,
|
||||||
|
struct addrinfo **result,
|
||||||
|
int line, const char *source)
|
||||||
|
{
|
||||||
|
int res=(getaddrinfo)(hostname, service, hints, result);
|
||||||
|
if(0 == res) {
|
||||||
|
/* success */
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
|
||||||
|
source, line, (void *)*result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
|
||||||
|
source, line);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||||
|
char *host, size_t hostlen,
|
||||||
|
char *serv, size_t servlen, int flags,
|
||||||
|
int line, const char *source)
|
||||||
|
{
|
||||||
|
int res=(getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags);
|
||||||
|
if(0 == res) {
|
||||||
|
/* success */
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "GETNAME %s:%d getnameinfo()\n",
|
||||||
|
source, line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "GETNAME %s:%d getnameinfo() failed = %d\n",
|
||||||
|
source, line, res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void curl_dofreeaddrinfo(struct addrinfo *freethis,
|
||||||
|
int line, const char *source)
|
||||||
|
{
|
||||||
|
(freeaddrinfo)(freethis);
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
|
||||||
|
source, line, (void *)freethis);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
|
||||||
|
* been set and returns TRUE if they are OK.
|
||||||
|
*/
|
||||||
|
bool Curl_ipvalid(struct SessionHandle *data)
|
||||||
|
{
|
||||||
|
if(data->set.ip_version == CURL_IPRESOLVE_V6) {
|
||||||
|
/* see if we have an IPv6 stack */
|
||||||
|
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (s == CURL_SOCKET_BAD)
|
||||||
|
/* an ipv6 address was requested and we can't get/use one */
|
||||||
|
return FALSE;
|
||||||
|
sclose(s);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef USE_THREADING_GETADDRINFO
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() when built ipv6-enabled (non-threading version).
|
||||||
|
*
|
||||||
|
* Returns name information about the given hostname and port number. If
|
||||||
|
* successful, the 'addrinfo' is returned and the forth argument will point to
|
||||||
|
* memory we need to free after use. That memory *MUST* be freed with
|
||||||
|
* Curl_freeaddrinfo(), nothing else.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp)
|
||||||
|
{
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
int error;
|
||||||
|
char sbuf[NI_MAXSERV];
|
||||||
|
curl_socket_t s;
|
||||||
|
int pf;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
*waitp=0; /* don't wait, we have the response now */
|
||||||
|
|
||||||
|
/* see if we have an IPv6 stack */
|
||||||
|
s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
/* Some non-IPv6 stacks have been found to make very slow name resolves
|
||||||
|
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
|
||||||
|
* the stack seems to be a non-ipv6 one. */
|
||||||
|
|
||||||
|
pf = PF_INET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
|
||||||
|
* possible checks. And close the socket again.
|
||||||
|
*/
|
||||||
|
sclose(s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a more limited name resolve has been requested.
|
||||||
|
*/
|
||||||
|
switch(data->set.ip_version) {
|
||||||
|
case CURL_IPRESOLVE_V4:
|
||||||
|
pf = PF_INET;
|
||||||
|
break;
|
||||||
|
case CURL_IPRESOLVE_V6:
|
||||||
|
pf = PF_INET6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pf = PF_UNSPEC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = pf;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
snprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||||
|
error = getaddrinfo(hostname, sbuf, &hints, &res);
|
||||||
|
if (error) {
|
||||||
|
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif /* USE_THREADING_GETADDRINFO */
|
||||||
|
#endif /* ipv6 */
|
||||||
|
|
||||||
149
lib/hostsyn.c
Normal file
149
lib/hostsyn.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for builds using synchronous name resolves
|
||||||
|
**********************************************************************/
|
||||||
|
#ifdef CURLRES_SYNCH
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return
|
||||||
|
* wait==TRUE, so this function will never be called. If it still gets called,
|
||||||
|
* we return failure at once.
|
||||||
|
*
|
||||||
|
* We provide this function only to allow multi.c to remain unaware if we are
|
||||||
|
* doing asynch resolves or not.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **entry)
|
||||||
|
{
|
||||||
|
(void)conn;
|
||||||
|
*entry=NULL;
|
||||||
|
return CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will never be called when synch-built. If it still gets
|
||||||
|
* called, we return failure at once.
|
||||||
|
*
|
||||||
|
* We provide this function only to allow multi.c to remain unaware if we are
|
||||||
|
* doing asynch resolves or not.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **dns)
|
||||||
|
{
|
||||||
|
(void)conn;
|
||||||
|
*dns = NULL;
|
||||||
|
|
||||||
|
return CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We just return OK, this function is never actually used for synch builds.
|
||||||
|
* It is present here to keep #ifdefs out from multi.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
CURLcode Curl_fdset(struct connectdata *conn,
|
||||||
|
fd_set *read_fd_set,
|
||||||
|
fd_set *write_fd_set,
|
||||||
|
int *max_fdp)
|
||||||
|
{
|
||||||
|
(void)conn;
|
||||||
|
(void)read_fd_set;
|
||||||
|
(void)write_fd_set;
|
||||||
|
(void)max_fdp;
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* truly sync */
|
||||||
550
lib/hostthre.c
Normal file
550
lib/hostthre.c
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define _REENTRANT
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h> /* required for free() prototypes */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for the close() proto */
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
#include <in.h>
|
||||||
|
#include <inet.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SETJMP_H
|
||||||
|
#include <setjmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||||
|
#undef in_addr_t
|
||||||
|
#define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "share.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
#include "url.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for Windows threaded name resolves builds
|
||||||
|
**********************************************************************/
|
||||||
|
#ifdef CURLRES_THREADED
|
||||||
|
|
||||||
|
/* This function is used to init a threaded resolve */
|
||||||
|
static bool init_resolve_thread(struct connectdata *conn,
|
||||||
|
const char *hostname, int port,
|
||||||
|
const Curl_addrinfo *hints);
|
||||||
|
|
||||||
|
#ifdef CURLRES_IPV4
|
||||||
|
#define THREAD_FUNC gethostbyname_thread
|
||||||
|
#define THREAD_NAME "gethostbyname_thread"
|
||||||
|
#else
|
||||||
|
#define THREAD_FUNC getaddrinfo_thread
|
||||||
|
#define THREAD_NAME "getaddrinfo_thread"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG_THREADING_GETHOSTBYNAME) || \
|
||||||
|
defined(DEBUG_THREADING_GETADDRINFO)
|
||||||
|
/* If this is defined, provide tracing */
|
||||||
|
#define TRACE(args) \
|
||||||
|
do { trace_it("%u: ", __LINE__); trace_it args; } while (0)
|
||||||
|
|
||||||
|
static void trace_it (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static int do_trace = -1;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (do_trace == -1) {
|
||||||
|
const char *env = getenv("CURL_TRACE");
|
||||||
|
do_trace = (env && atoi(env) > 0);
|
||||||
|
}
|
||||||
|
if (!do_trace)
|
||||||
|
return;
|
||||||
|
va_start (args, fmt);
|
||||||
|
vfprintf (stderr, fmt, args);
|
||||||
|
fflush (stderr);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define TRACE(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_THREADING_GETADDRINFO
|
||||||
|
static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai)
|
||||||
|
{
|
||||||
|
TRACE(("dump_addrinfo:\n"));
|
||||||
|
for ( ; ai; ai = ai->ai_next) {
|
||||||
|
char buf [INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
trace_it(" fam %2d, CNAME %s, ",
|
||||||
|
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
|
||||||
|
if (Curl_printable_address(ai->ai_family, ai->ai_addr, buf, sizeof(buf)))
|
||||||
|
trace_it("%s\n", buf);
|
||||||
|
else
|
||||||
|
trace_it("failed; %s\n", Curl_strerror(conn,WSAGetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct thread_data {
|
||||||
|
HANDLE thread_hnd;
|
||||||
|
unsigned thread_id;
|
||||||
|
DWORD thread_status;
|
||||||
|
curl_socket_t dummy_sock; /* dummy for Curl_fdset() */
|
||||||
|
FILE *stderr_file;
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
struct addrinfo hints;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CURLRES_IPV4)
|
||||||
|
/*
|
||||||
|
* gethostbyname_thread() resolves a name, calls the Curl_addrinfo_callback
|
||||||
|
* and then exits.
|
||||||
|
*
|
||||||
|
* For builds without ARES/ENABLE_IPV6, create a resolver thread and wait on
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
static unsigned __stdcall gethostbyname_thread (void *arg)
|
||||||
|
{
|
||||||
|
struct connectdata *conn = (struct connectdata*) arg;
|
||||||
|
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
|
||||||
|
struct hostent *he;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Sharing the same _iob[] element with our parent thread should
|
||||||
|
* hopefully make printouts synchronised. I'm not sure it works
|
||||||
|
* with a static runtime lib (MSVC's libc.lib).
|
||||||
|
*/
|
||||||
|
*stderr = *td->stderr_file;
|
||||||
|
|
||||||
|
WSASetLastError (conn->async.status = NO_DATA); /* pending status */
|
||||||
|
he = gethostbyname (conn->async.hostname);
|
||||||
|
if (he) {
|
||||||
|
Curl_addrinfo_callback(conn, CURL_ASYNC_SUCCESS, he);
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Curl_addrinfo_callback(conn, (int)WSAGetLastError(), NULL);
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
|
||||||
|
he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
|
||||||
|
return (rc);
|
||||||
|
/* An implicit _endthreadex() here */
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(CURLRES_IPV6)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getaddrinfo_thread() resolves a name, calls Curl_addrinfo_callback and then
|
||||||
|
* exits.
|
||||||
|
*
|
||||||
|
* For builds without ARES, but with ENABLE_IPV6, create a resolver thread
|
||||||
|
* and wait on it.
|
||||||
|
*/
|
||||||
|
static unsigned __stdcall getaddrinfo_thread (void *arg)
|
||||||
|
{
|
||||||
|
struct connectdata *conn = (struct connectdata*) arg;
|
||||||
|
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
|
||||||
|
struct addrinfo *res;
|
||||||
|
char service [NI_MAXSERV];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
*stderr = *td->stderr_file;
|
||||||
|
|
||||||
|
itoa(conn->async.port, service, 10);
|
||||||
|
|
||||||
|
WSASetLastError(conn->async.status = NO_DATA); /* pending status */
|
||||||
|
|
||||||
|
rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
#ifdef DEBUG_THREADING_GETADDRINFO
|
||||||
|
dump_addrinfo (conn, res);
|
||||||
|
#endif
|
||||||
|
Curl_addrinfo_callback(conn, CURL_ASYNC_SUCCESS, res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Curl_addrinfo_callback(conn, (int)WSAGetLastError(), NULL);
|
||||||
|
TRACE(("Winsock-error %d, no address\n", conn->async.status));
|
||||||
|
}
|
||||||
|
return (rc);
|
||||||
|
/* An implicit _endthreadex() here */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroy_thread_data() cleans up async resolver data.
|
||||||
|
* Complementary of ares_destroy.
|
||||||
|
*/
|
||||||
|
static void destroy_thread_data (struct Curl_async *async)
|
||||||
|
{
|
||||||
|
if (async->hostname)
|
||||||
|
free(async->hostname);
|
||||||
|
|
||||||
|
if (async->os_specific) {
|
||||||
|
curl_socket_t sock = ((const struct thread_data*)async->os_specific)->dummy_sock;
|
||||||
|
|
||||||
|
if (sock != CURL_SOCKET_BAD)
|
||||||
|
sclose(sock);
|
||||||
|
free(async->os_specific);
|
||||||
|
}
|
||||||
|
async->hostname = NULL;
|
||||||
|
async->os_specific = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_resolve_thread() starts a new thread that performs the actual
|
||||||
|
* resolve. This function returns before the resolve is done.
|
||||||
|
*
|
||||||
|
* Returns FALSE in case of failure, otherwise TRUE.
|
||||||
|
*/
|
||||||
|
static bool init_resolve_thread (struct connectdata *conn,
|
||||||
|
const char *hostname, int port,
|
||||||
|
const Curl_addrinfo *hints)
|
||||||
|
{
|
||||||
|
struct thread_data *td = calloc(sizeof(*td), 1);
|
||||||
|
|
||||||
|
if (!td) {
|
||||||
|
SetLastError(ENOMEM);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(conn->async.hostname);
|
||||||
|
conn->async.hostname = strdup(hostname);
|
||||||
|
if (!conn->async.hostname) {
|
||||||
|
free(td);
|
||||||
|
SetLastError(ENOMEM);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->async.port = port;
|
||||||
|
conn->async.done = FALSE;
|
||||||
|
conn->async.status = 0;
|
||||||
|
conn->async.dns = NULL;
|
||||||
|
conn->async.os_specific = (void*) td;
|
||||||
|
|
||||||
|
td->dummy_sock = CURL_SOCKET_BAD;
|
||||||
|
td->stderr_file = stderr;
|
||||||
|
td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
|
||||||
|
conn, 0, &td->thread_id);
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
curlassert(hints);
|
||||||
|
td->hints = *hints;
|
||||||
|
#else
|
||||||
|
(void) hints;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!td->thread_hnd) {
|
||||||
|
SetLastError(errno);
|
||||||
|
TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno)));
|
||||||
|
destroy_thread_data(&conn->async);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* This socket is only to keep Curl_fdset() and select() happy; should never
|
||||||
|
* become signalled for read/write since it's unbound but Windows needs
|
||||||
|
* atleast 1 socket in select().
|
||||||
|
*/
|
||||||
|
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_wait_for_resolv() waits for a resolve to finish. This function should
|
||||||
|
* be avoided since using this risk getting the multi interface to "hang".
|
||||||
|
*
|
||||||
|
* If 'entry' is non-NULL, make it point to the resolved dns entry
|
||||||
|
*
|
||||||
|
* This is the version for resolves-in-a-thread.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **entry)
|
||||||
|
{
|
||||||
|
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
long timeout;
|
||||||
|
DWORD status, ticks;
|
||||||
|
CURLcode rc;
|
||||||
|
|
||||||
|
curlassert (conn && td);
|
||||||
|
|
||||||
|
/* now, see if there's a connect timeout or a regular timeout to
|
||||||
|
use instead of the default one */
|
||||||
|
timeout =
|
||||||
|
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
|
||||||
|
conn->data->set.timeout ? conn->data->set.timeout :
|
||||||
|
CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
|
||||||
|
ticks = GetTickCount();
|
||||||
|
|
||||||
|
status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout);
|
||||||
|
if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) {
|
||||||
|
/* Thread finished before timeout; propagate Winsock error to this thread.
|
||||||
|
* 'conn->async.done = TRUE' is set in Curl_addrinfo_callback().
|
||||||
|
*/
|
||||||
|
WSASetLastError(conn->async.status);
|
||||||
|
GetExitCodeThread(td->thread_hnd, &td->thread_status);
|
||||||
|
TRACE(("%s() status %lu, thread retval %lu, ",
|
||||||
|
THREAD_NAME, status, td->thread_status));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
conn->async.done = TRUE;
|
||||||
|
td->thread_status = (DWORD)-1;
|
||||||
|
TRACE(("%s() timeout, ", THREAD_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
|
||||||
|
|
||||||
|
CloseHandle(td->thread_hnd);
|
||||||
|
|
||||||
|
if(entry)
|
||||||
|
*entry = conn->async.dns;
|
||||||
|
|
||||||
|
rc = CURLE_OK;
|
||||||
|
|
||||||
|
if (!conn->async.dns) {
|
||||||
|
/* a name was not resolved */
|
||||||
|
if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
|
||||||
|
failf(data, "Resolving host timed out: %s", conn->host.name);
|
||||||
|
rc = CURLE_OPERATION_TIMEDOUT;
|
||||||
|
}
|
||||||
|
else if(conn->async.done) {
|
||||||
|
failf(data, "Could not resolve host: %s; %s",
|
||||||
|
conn->host.name, Curl_strerror(conn,conn->async.status));
|
||||||
|
rc = CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = CURLE_OPERATION_TIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_thread_data(&conn->async);
|
||||||
|
|
||||||
|
if(CURLE_OK != rc)
|
||||||
|
/* close the connection, since we must not return failure from here
|
||||||
|
without cleaning up this connection properly */
|
||||||
|
Curl_disconnect(conn);
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
|
||||||
|
* request has completed. It should also make sure to time-out if the
|
||||||
|
* operation seems to take too long.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||||
|
struct Curl_dns_entry **entry)
|
||||||
|
{
|
||||||
|
*entry = NULL;
|
||||||
|
|
||||||
|
if (conn->async.done) {
|
||||||
|
/* we're done */
|
||||||
|
destroy_thread_data(&conn->async);
|
||||||
|
if (!conn->async.dns) {
|
||||||
|
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
|
||||||
|
return CURLE_COULDNT_RESOLVE_HOST;
|
||||||
|
}
|
||||||
|
*entry = conn->async.dns;
|
||||||
|
TRACE(("resolved okay, dns %p\n", *entry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TRACE(("not yet\n"));
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CURLcode Curl_fdset(struct connectdata *conn,
|
||||||
|
fd_set *read_fd_set,
|
||||||
|
fd_set *write_fd_set,
|
||||||
|
int *max_fdp)
|
||||||
|
{
|
||||||
|
const struct thread_data *td =
|
||||||
|
(const struct thread_data *) conn->async.os_specific;
|
||||||
|
|
||||||
|
if (td && td->dummy_sock != CURL_SOCKET_BAD) {
|
||||||
|
FD_SET(td->dummy_sock,write_fd_set);
|
||||||
|
*max_fdp = td->dummy_sock;
|
||||||
|
}
|
||||||
|
(void) read_fd_set;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CURLRES_IPV4
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() - for Windows threading without ENABLE_IPV6.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp)
|
||||||
|
{
|
||||||
|
struct hostent *h = NULL;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
in_addr_t in;
|
||||||
|
|
||||||
|
*waitp = 0; /* don't wait, we act synchronously */
|
||||||
|
|
||||||
|
in = inet_addr(hostname);
|
||||||
|
if (in != CURL_INADDR_NONE)
|
||||||
|
/* This is a dotted IP address 123.123.123.123-style */
|
||||||
|
return Curl_ip2addr(in, hostname);
|
||||||
|
|
||||||
|
/* fire up a new resolver thread! */
|
||||||
|
if (init_resolve_thread(conn, hostname, port, NULL)) {
|
||||||
|
*waitp = TRUE; /* please wait for the response */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall-back to blocking version */
|
||||||
|
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
|
||||||
|
hostname, GetLastError());
|
||||||
|
|
||||||
|
h = gethostbyname(hostname);
|
||||||
|
if (!h) {
|
||||||
|
infof(data, "gethostbyname(2) failed for %s:%d; %s\n",
|
||||||
|
hostname, port, Curl_strerror(conn,WSAGetLastError()));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
#endif /* CURLRES_IPV4 */
|
||||||
|
|
||||||
|
#ifdef CURLRES_IPV6
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo() - for Windows threading IPv6 enabled
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
int *waitp)
|
||||||
|
{
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
int error;
|
||||||
|
char sbuf[NI_MAXSERV];
|
||||||
|
curl_socket_t s;
|
||||||
|
int pf;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
*waitp = FALSE; /* default to synch response */
|
||||||
|
|
||||||
|
/* see if we have an IPv6 stack */
|
||||||
|
s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (s == CURL_SOCKET_BAD) {
|
||||||
|
/* Some non-IPv6 stacks have been found to make very slow name resolves
|
||||||
|
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
|
||||||
|
* the stack seems to be a non-ipv6 one. */
|
||||||
|
|
||||||
|
pf = PF_INET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
|
||||||
|
* possible checks. And close the socket again.
|
||||||
|
*/
|
||||||
|
sclose(s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a more limited name resolve has been requested.
|
||||||
|
*/
|
||||||
|
switch(data->set.ip_version) {
|
||||||
|
case CURL_IPRESOLVE_V4:
|
||||||
|
pf = PF_INET;
|
||||||
|
break;
|
||||||
|
case CURL_IPRESOLVE_V6:
|
||||||
|
pf = PF_INET6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pf = PF_UNSPEC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = pf;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
itoa(port, sbuf, 10);
|
||||||
|
|
||||||
|
/* fire up a new resolver thread! */
|
||||||
|
if (init_resolve_thread(conn, hostname, port, &hints)) {
|
||||||
|
*waitp = TRUE; /* please wait for the response */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall-back to blocking version */
|
||||||
|
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
|
||||||
|
hostname, GetLastError());
|
||||||
|
|
||||||
|
error = getaddrinfo(hostname, sbuf, &hints, &res);
|
||||||
|
if (error) {
|
||||||
|
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
|
||||||
|
hostname, port, Curl_strerror(conn,WSAGetLastError()));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif /* CURLRES_IPV6 */
|
||||||
|
#endif /* CURLRES_THREADED */
|
||||||
755
lib/http.c
755
lib/http.c
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
|||||||
|
|
||||||
/* protocol-specific functions set up to be called by the main engine */
|
/* protocol-specific functions set up to be called by the main engine */
|
||||||
CURLcode Curl_http(struct connectdata *conn);
|
CURLcode Curl_http(struct connectdata *conn);
|
||||||
CURLcode Curl_http_done(struct connectdata *conn);
|
CURLcode Curl_http_done(struct connectdata *, CURLcode);
|
||||||
CURLcode Curl_http_connect(struct connectdata *conn);
|
CURLcode Curl_http_connect(struct connectdata *conn);
|
||||||
|
|
||||||
/* The following functions are defined in http_chunks.c */
|
/* The following functions are defined in http_chunks.c */
|
||||||
@@ -45,9 +45,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
|
|||||||
|
|
||||||
/* These functions are in http.c */
|
/* These functions are in http.c */
|
||||||
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
|
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
|
||||||
CURLcode Curl_http_auth(struct connectdata *conn,
|
CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||||
int httpcode, char *header);
|
int httpcode, char *header);
|
||||||
void Curl_http_auth_act(struct connectdata *conn);
|
CURLcode Curl_http_auth_act(struct connectdata *conn);
|
||||||
|
|
||||||
int Curl_http_should_fail(struct connectdata *conn);
|
int Curl_http_should_fail(struct connectdata *conn);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,16 +33,15 @@
|
|||||||
#include "urldata.h" /* it includes http_chunks.h */
|
#include "urldata.h" /* it includes http_chunks.h */
|
||||||
#include "sendf.h" /* for the client write stuff */
|
#include "sendf.h" /* for the client write stuff */
|
||||||
|
|
||||||
#include "content_encoding.h" /* 08/29/02 jhrg */
|
#include "content_encoding.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Chunk format (simplified):
|
* Chunk format (simplified):
|
||||||
@@ -179,8 +178,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
piece = (ch->datasize >= length)?length:ch->datasize;
|
piece = (ch->datasize >= length)?length:ch->datasize;
|
||||||
|
|
||||||
/* Write the data portion available */
|
/* Write the data portion available */
|
||||||
/* Added content-encoding here; untested but almost identical to the
|
|
||||||
tested code in transfer.c. 08/29/02 jhrg */
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
switch (conn->keep.content_encoding) {
|
switch (conn->keep.content_encoding) {
|
||||||
case IDENTITY:
|
case IDENTITY:
|
||||||
@@ -194,13 +191,15 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
case DEFLATE:
|
case DEFLATE:
|
||||||
/* update conn->keep.str to point to the chunk data. */
|
/* update conn->keep.str to point to the chunk data. */
|
||||||
conn->keep.str = datap;
|
conn->keep.str = datap;
|
||||||
result = Curl_unencode_deflate_write(conn->data, &conn->keep, piece);
|
result = Curl_unencode_deflate_write(conn->data, &conn->keep,
|
||||||
|
(ssize_t)piece);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GZIP:
|
case GZIP:
|
||||||
/* update conn->keep.str to point to the chunk data. */
|
/* update conn->keep.str to point to the chunk data. */
|
||||||
conn->keep.str = datap;
|
conn->keep.str = datap;
|
||||||
result = Curl_unencode_gzip_write(conn->data, &conn->keep, piece);
|
result = Curl_unencode_gzip_write(conn->data, &conn->keep,
|
||||||
|
(ssize_t)piece);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMPRESS:
|
case COMPRESS:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -33,33 +33,46 @@
|
|||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
|
#include "base64.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "http_digest.h"
|
#include "http_digest.h"
|
||||||
|
#include "strtok.h"
|
||||||
#include "url.h" /* for Curl_safefree() */
|
#include "url.h" /* for Curl_safefree() */
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Test example header:
|
/* Test example headers:
|
||||||
|
|
||||||
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
|
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
|
||||||
|
Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CURLdigest Curl_input_digest(struct connectdata *conn,
|
CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||||
char *header) /* rest of the www-authenticate:
|
bool proxy,
|
||||||
|
char *header) /* rest of the *-authenticate:
|
||||||
header */
|
header */
|
||||||
{
|
{
|
||||||
bool more = TRUE;
|
bool more = TRUE;
|
||||||
|
char *token = NULL;
|
||||||
|
char *tmp = NULL;
|
||||||
|
bool foundAuth = FALSE;
|
||||||
|
bool foundAuthInt = FALSE;
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
bool before = FALSE; /* got a nonce before */
|
bool before = FALSE; /* got a nonce before */
|
||||||
struct digestdata *d = &data->state.digest;
|
struct digestdata *d;
|
||||||
|
|
||||||
|
if(proxy) {
|
||||||
|
d = &data->state.proxydigest;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = &data->state.digest;
|
||||||
|
}
|
||||||
|
|
||||||
/* skip initial whitespaces */
|
/* skip initial whitespaces */
|
||||||
while(*header && isspace((int)*header))
|
while(*header && isspace((int)*header))
|
||||||
@@ -73,7 +86,7 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
|||||||
before = TRUE;
|
before = TRUE;
|
||||||
|
|
||||||
/* clear off any former leftovers and init to defaults */
|
/* clear off any former leftovers and init to defaults */
|
||||||
Curl_digest_cleanup(data);
|
Curl_digest_cleanup_one(d);
|
||||||
|
|
||||||
while(more) {
|
while(more) {
|
||||||
char value[32];
|
char value[32];
|
||||||
@@ -82,7 +95,7 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
|||||||
|
|
||||||
while(*header && isspace((int)*header))
|
while(*header && isspace((int)*header))
|
||||||
header++;
|
header++;
|
||||||
|
|
||||||
/* how big can these strings be? */
|
/* how big can these strings be? */
|
||||||
if((2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
|
if((2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
|
||||||
value, content)) ||
|
value, content)) ||
|
||||||
@@ -92,18 +105,59 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
|||||||
value, content)) ) {
|
value, content)) ) {
|
||||||
if(strequal(value, "nonce")) {
|
if(strequal(value, "nonce")) {
|
||||||
d->nonce = strdup(content);
|
d->nonce = strdup(content);
|
||||||
|
if(!d->nonce)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
}
|
}
|
||||||
else if(strequal(value, "stale")) {
|
else if(strequal(value, "stale")) {
|
||||||
if(strequal(content, "true"))
|
if(strequal(content, "true")) {
|
||||||
d->stale = TRUE;
|
d->stale = TRUE;
|
||||||
}
|
d->nc = 1; /* we make a new nonce now */
|
||||||
else if(strequal(value, "cnonce")) {
|
}
|
||||||
d->cnonce = strdup(content);
|
|
||||||
}
|
}
|
||||||
else if(strequal(value, "realm")) {
|
else if(strequal(value, "realm")) {
|
||||||
d->realm = strdup(content);
|
d->realm = strdup(content);
|
||||||
|
if(!d->realm)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "opaque")) {
|
||||||
|
d->opaque = strdup(content);
|
||||||
|
if(!d->opaque)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "qop")) {
|
||||||
|
char *tok_buf;
|
||||||
|
/* tokenize the list and choose auth if possible, use a temporary
|
||||||
|
clone of the buffer since strtok_r() ruins it */
|
||||||
|
tmp = strdup(content);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
|
token = strtok_r(tmp, ",", &tok_buf);
|
||||||
|
while (token != NULL) {
|
||||||
|
if (strequal(token, "auth")) {
|
||||||
|
foundAuth = TRUE;
|
||||||
|
}
|
||||||
|
else if (strequal(token, "auth-int")) {
|
||||||
|
foundAuthInt = TRUE;
|
||||||
|
}
|
||||||
|
token = strtok_r(NULL, ",", &tok_buf);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
/*select only auth o auth-int. Otherwise, ignore*/
|
||||||
|
if (foundAuth) {
|
||||||
|
d->qop = strdup("auth");
|
||||||
|
if(!d->qop)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
|
}
|
||||||
|
else if (foundAuthInt) {
|
||||||
|
d->qop = strdup("auth-int");
|
||||||
|
if(!d->qop)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(strequal(value, "algorithm")) {
|
else if(strequal(value, "algorithm")) {
|
||||||
|
d->algorithm = strdup(content);
|
||||||
|
if(!d->algorithm)
|
||||||
|
return CURLDIGEST_NOMEM;
|
||||||
if(strequal(content, "MD5-sess"))
|
if(strequal(content, "MD5-sess"))
|
||||||
d->algo = CURLDIGESTALGO_MD5SESS;
|
d->algo = CURLDIGESTALGO_MD5SESS;
|
||||||
else if(strequal(content, "MD5"))
|
else if(strequal(content, "MD5"))
|
||||||
@@ -116,18 +170,17 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
totlen = strlen(value)+strlen(content)+3;
|
totlen = strlen(value)+strlen(content)+3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break; /* we're done here */
|
break; /* we're done here */
|
||||||
|
|
||||||
header += totlen;
|
header += totlen;
|
||||||
if(',' == *header)
|
if(',' == *header)
|
||||||
/* allow the list to be comma-separated */
|
/* allow the list to be comma-separated */
|
||||||
header++;
|
header++;
|
||||||
}
|
}
|
||||||
/* We had a nonce since before, and we got another one now without
|
/* We had a nonce since before, and we got another one now without
|
||||||
'stale=true'. This means we provided bad credentials in the previous
|
'stale=true'. This means we provided bad credentials in the previous
|
||||||
request */
|
request */
|
||||||
|
|
||||||
if(before && !d->stale)
|
if(before && !d->stale)
|
||||||
return CURLDIGEST_BAD;
|
return CURLDIGEST_BAD;
|
||||||
|
|
||||||
@@ -135,7 +188,7 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
|||||||
if(!d->nonce)
|
if(!d->nonce)
|
||||||
return CURLDIGEST_BAD;
|
return CURLDIGEST_BAD;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* else not a digest, get out */
|
/* else not a digest, get out */
|
||||||
return CURLDIGEST_NONE;
|
return CURLDIGEST_NONE;
|
||||||
|
|
||||||
@@ -152,6 +205,7 @@ static void md5_to_ascii(unsigned char *source, /* 16 bytes */
|
|||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_output_digest(struct connectdata *conn,
|
CURLcode Curl_output_digest(struct connectdata *conn,
|
||||||
|
bool proxy,
|
||||||
unsigned char *request,
|
unsigned char *request,
|
||||||
unsigned char *uripath)
|
unsigned char *uripath)
|
||||||
{
|
{
|
||||||
@@ -159,17 +213,53 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
this sorted out, I must urge you dear friend to read up on the RFC2617
|
this sorted out, I must urge you dear friend to read up on the RFC2617
|
||||||
section 3.2.2, */
|
section 3.2.2, */
|
||||||
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
||||||
unsigned char ha1[33]; /* 32 digits and 1 zero byte */
|
|
||||||
unsigned char ha2[33];
|
|
||||||
unsigned char request_digest[33];
|
unsigned char request_digest[33];
|
||||||
unsigned char *md5this;
|
unsigned char *md5this;
|
||||||
|
unsigned char *ha1;
|
||||||
|
unsigned char ha2[33];/* 32 digits and 1 zero byte */
|
||||||
|
char cnoncebuf[7];
|
||||||
|
char *cnonce;
|
||||||
|
char *tmp = NULL;
|
||||||
|
struct timeval now;
|
||||||
|
struct auth *authp;
|
||||||
|
char **userp;
|
||||||
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct digestdata *d = &data->state.digest;
|
struct digestdata *d;
|
||||||
|
|
||||||
|
if(proxy) {
|
||||||
|
d = &data->state.proxydigest;
|
||||||
|
authp = &data->state.authproxy;
|
||||||
|
userp = &conn->allocptr.proxyuserpwd;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = &data->state.digest;
|
||||||
|
authp = &data->state.authhost;
|
||||||
|
userp = &conn->allocptr.userpwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!d->nonce) {
|
||||||
|
authp->done = FALSE;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
authp->done = TRUE;
|
||||||
|
|
||||||
|
if(!d->nc)
|
||||||
|
d->nc = 1;
|
||||||
|
|
||||||
|
if(!d->cnonce) {
|
||||||
|
/* Generate a cnonce */
|
||||||
|
now = Curl_tvnow();
|
||||||
|
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", now.tv_sec);
|
||||||
|
if(Curl_base64_encode(cnoncebuf, strlen(cnoncebuf), &cnonce))
|
||||||
|
d->cnonce = cnonce;
|
||||||
|
else
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if the algorithm is "MD5" or unspecified (which then defaults to MD5):
|
if the algorithm is "MD5" or unspecified (which then defaults to MD5):
|
||||||
|
|
||||||
A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
||||||
|
|
||||||
if the algorithm is "MD5-sess" then:
|
if the algorithm is "MD5-sess" then:
|
||||||
@@ -177,40 +267,76 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
|
A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
|
||||||
":" unq(nonce-value) ":" unq(cnonce-value)
|
":" unq(nonce-value) ":" unq(cnonce-value)
|
||||||
*/
|
*/
|
||||||
if(d->algo == CURLDIGESTALGO_MD5SESS) {
|
|
||||||
md5this = (unsigned char *)
|
md5this = (unsigned char *)
|
||||||
aprintf("%s:%s:%s:%s:%s",
|
aprintf("%s:%s:%s", conn->user, d->realm, conn->passwd);
|
||||||
conn->user,
|
if(!md5this)
|
||||||
d->realm,
|
return CURLE_OUT_OF_MEMORY;
|
||||||
conn->passwd,
|
|
||||||
d->nonce,
|
|
||||||
d->cnonce);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
md5this = (unsigned char *)
|
|
||||||
aprintf("%s:%s:%s",
|
|
||||||
conn->user,
|
|
||||||
d->realm,
|
|
||||||
conn->passwd);
|
|
||||||
}
|
|
||||||
Curl_md5it(md5buf, md5this);
|
Curl_md5it(md5buf, md5this);
|
||||||
free(md5this); /* free this again */
|
free(md5this); /* free this again */
|
||||||
|
|
||||||
|
ha1 = (unsigned char *)malloc(33); /* 32 digits and 1 zero byte */
|
||||||
|
if(!ha1)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
md5_to_ascii(md5buf, ha1);
|
md5_to_ascii(md5buf, ha1);
|
||||||
|
|
||||||
|
if(d->algo == CURLDIGESTALGO_MD5SESS) {
|
||||||
|
/* nonce and cnonce are OUTSIDE the hash */
|
||||||
|
tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
|
||||||
|
free(ha1);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
ha1 = (unsigned char *)tmp;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A2 = Method ":" digest-uri-value
|
If the "qop" directive's value is "auth" or is unspecified, then A2 is:
|
||||||
|
|
||||||
|
A2 = Method ":" digest-uri-value
|
||||||
|
|
||||||
|
If the "qop" value is "auth-int", then A2 is:
|
||||||
|
|
||||||
|
A2 = Method ":" digest-uri-value ":" H(entity-body)
|
||||||
|
|
||||||
(The "Method" value is the HTTP request method as specified in section
|
(The "Method" value is the HTTP request method as specified in section
|
||||||
5.1.1 of RFC 2616)
|
5.1.1 of RFC 2616)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
|
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
|
||||||
|
if(!md5this) {
|
||||||
|
free(ha1);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->qop && strequal(d->qop, "auth-int")) {
|
||||||
|
/* We don't support auth-int at the moment. I can't see a easy way to get
|
||||||
|
entity-body here */
|
||||||
|
/* TODO: Append H(entity-body)*/
|
||||||
|
}
|
||||||
Curl_md5it(md5buf, md5this);
|
Curl_md5it(md5buf, md5this);
|
||||||
free(md5this); /* free this again */
|
free(md5this); /* free this again */
|
||||||
md5_to_ascii(md5buf, ha2);
|
md5_to_ascii(md5buf, ha2);
|
||||||
|
|
||||||
md5this = (unsigned char *)aprintf("%s:%s:%s", ha1, d->nonce,
|
if (d->qop) {
|
||||||
ha2);
|
md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s",
|
||||||
|
ha1,
|
||||||
|
d->nonce,
|
||||||
|
d->nc,
|
||||||
|
d->cnonce,
|
||||||
|
d->qop,
|
||||||
|
ha2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
md5this = (unsigned char *)aprintf("%s:%s:%s",
|
||||||
|
ha1,
|
||||||
|
d->nonce,
|
||||||
|
ha2);
|
||||||
|
}
|
||||||
|
free(ha1);
|
||||||
|
if(!md5this)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
Curl_md5it(md5buf, md5this);
|
Curl_md5it(md5buf, md5this);
|
||||||
free(md5this); /* free this again */
|
free(md5this); /* free this again */
|
||||||
md5_to_ascii(md5buf, request_digest);
|
md5_to_ascii(md5buf, request_digest);
|
||||||
@@ -222,26 +348,82 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Curl_safefree(conn->allocptr.userpwd);
|
Curl_safefree(conn->allocptr.userpwd);
|
||||||
conn->allocptr.userpwd =
|
|
||||||
aprintf( "Authorization: Digest "
|
if (d->qop) {
|
||||||
"username=\"%s\", "
|
*userp =
|
||||||
"realm=\"%s\", "
|
aprintf( "%sAuthorization: Digest "
|
||||||
"nonce=\"%s\", "
|
"username=\"%s\", "
|
||||||
"uri=\"%s\", "
|
"realm=\"%s\", "
|
||||||
"response=\"%s\"\r\n",
|
"nonce=\"%s\", "
|
||||||
conn->user,
|
"uri=\"%s\", "
|
||||||
d->realm,
|
"cnonce=\"%s\", "
|
||||||
d->nonce,
|
"nc=%08x, "
|
||||||
uripath, /* this is the PATH part of the URL */
|
"qop=\"%s\", "
|
||||||
request_digest );
|
"response=\"%s\"",
|
||||||
|
proxy?"Proxy-":"",
|
||||||
|
conn->user,
|
||||||
|
d->realm,
|
||||||
|
d->nonce,
|
||||||
|
uripath, /* this is the PATH part of the URL */
|
||||||
|
d->cnonce,
|
||||||
|
d->nc,
|
||||||
|
d->qop,
|
||||||
|
request_digest);
|
||||||
|
|
||||||
|
if(strequal(d->qop, "auth"))
|
||||||
|
d->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 padded
|
||||||
|
which tells to the server how many times you are using the
|
||||||
|
same nonce in the qop=auth mode. */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*userp =
|
||||||
|
aprintf( "%sAuthorization: Digest "
|
||||||
|
"username=\"%s\", "
|
||||||
|
"realm=\"%s\", "
|
||||||
|
"nonce=\"%s\", "
|
||||||
|
"uri=\"%s\", "
|
||||||
|
"response=\"%s\"",
|
||||||
|
proxy?"Proxy-":"",
|
||||||
|
conn->user,
|
||||||
|
d->realm,
|
||||||
|
d->nonce,
|
||||||
|
uripath, /* this is the PATH part of the URL */
|
||||||
|
request_digest);
|
||||||
|
}
|
||||||
|
if(!*userp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Add optional fields */
|
||||||
|
if(d->opaque) {
|
||||||
|
/* append opaque */
|
||||||
|
tmp = aprintf("%s, opaque=\"%s\"", *userp, d->opaque);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
free(*userp);
|
||||||
|
*userp = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d->algorithm) {
|
||||||
|
/* append algorithm */
|
||||||
|
tmp = aprintf("%s, algorithm=\"%s\"", *userp, d->algorithm);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
free(*userp);
|
||||||
|
*userp = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append CRLF to the userpwd header */
|
||||||
|
tmp = (char*) realloc(*userp, strlen(*userp) + 3 + 1);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
strcat(tmp, "\r\n");
|
||||||
|
*userp = tmp;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curl_digest_cleanup(struct SessionHandle *data)
|
void Curl_digest_cleanup_one(struct digestdata *d)
|
||||||
{
|
{
|
||||||
struct digestdata *d = &data->state.digest;
|
|
||||||
|
|
||||||
if(d->nonce)
|
if(d->nonce)
|
||||||
free(d->nonce);
|
free(d->nonce);
|
||||||
d->nonce = NULL;
|
d->nonce = NULL;
|
||||||
@@ -254,9 +436,28 @@ void Curl_digest_cleanup(struct SessionHandle *data)
|
|||||||
free(d->realm);
|
free(d->realm);
|
||||||
d->realm = NULL;
|
d->realm = NULL;
|
||||||
|
|
||||||
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
|
if(d->opaque)
|
||||||
|
free(d->opaque);
|
||||||
|
d->opaque = NULL;
|
||||||
|
|
||||||
|
if(d->qop)
|
||||||
|
free(d->qop);
|
||||||
|
d->qop = NULL;
|
||||||
|
|
||||||
|
if(d->algorithm)
|
||||||
|
free(d->algorithm);
|
||||||
|
d->algorithm = NULL;
|
||||||
|
|
||||||
|
d->nc = 0;
|
||||||
|
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
|
||||||
d->stale = FALSE; /* default means normal, not stale */
|
d->stale = FALSE; /* default means normal, not stale */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Curl_digest_cleanup(struct SessionHandle *data)
|
||||||
|
{
|
||||||
|
Curl_digest_cleanup_one(&data->state.digest);
|
||||||
|
Curl_digest_cleanup_one(&data->state.proxydigest);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ typedef enum {
|
|||||||
CURLDIGEST_NONE, /* not a digest */
|
CURLDIGEST_NONE, /* not a digest */
|
||||||
CURLDIGEST_BAD, /* a digest, but one we don't like */
|
CURLDIGEST_BAD, /* a digest, but one we don't like */
|
||||||
CURLDIGEST_BADALGO, /* unsupported algorithm requested */
|
CURLDIGEST_BADALGO, /* unsupported algorithm requested */
|
||||||
|
CURLDIGEST_NOMEM,
|
||||||
CURLDIGEST_FINE, /* a digest we act on */
|
CURLDIGEST_FINE, /* a digest we act on */
|
||||||
|
|
||||||
CURLDIGEST_LAST /* last entry in this enum, don't use */
|
CURLDIGEST_LAST /* last entry in this enum, don't use */
|
||||||
@@ -38,12 +39,15 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* this is for digest header input */
|
/* this is for digest header input */
|
||||||
CURLdigest Curl_input_digest(struct connectdata *conn, char *header);
|
CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||||
|
bool proxy, char *header);
|
||||||
|
|
||||||
/* this is for creating digest header output */
|
/* this is for creating digest header output */
|
||||||
CURLcode Curl_output_digest(struct connectdata *conn,
|
CURLcode Curl_output_digest(struct connectdata *conn,
|
||||||
|
bool proxy,
|
||||||
unsigned char *request,
|
unsigned char *request,
|
||||||
unsigned char *uripath);
|
unsigned char *uripath);
|
||||||
void Curl_digest_cleanup(struct SessionHandle *data);
|
void Curl_digest_cleanup(struct SessionHandle *data);
|
||||||
|
void Curl_digest_cleanup_one(struct digestdata *dig);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,14 +41,13 @@
|
|||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "http_negotiate.h"
|
#include "http_negotiate.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_gss_name(struct connectdata *conn, gss_name_t *server)
|
get_gss_name(struct connectdata *conn, gss_name_t *server)
|
||||||
@@ -71,10 +70,10 @@ get_gss_name(struct connectdata *conn, gss_name_t *server)
|
|||||||
else
|
else
|
||||||
service = "http";
|
service = "http";
|
||||||
|
|
||||||
token.length = strlen(service) + 1 + strlen(conn->hostname) + 1;
|
token.length = strlen(service) + 1 + strlen(conn->host.name) + 1;
|
||||||
if (token.length + 1 > sizeof(name))
|
if (token.length + 1 > sizeof(name))
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
sprintf(name, "%s@%s", service, conn->hostname);
|
sprintf(name, "%s@%s", service, conn->host.name);
|
||||||
|
|
||||||
token.value = (void *) name;
|
token.value = (void *) name;
|
||||||
major_status = gss_import_name(&minor_status,
|
major_status = gss_import_name(&minor_status,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
/* NTLM details:
|
/* NTLM details:
|
||||||
|
|
||||||
http://davenport.sourceforge.net/ntlm.html
|
http://davenport.sourceforge.net/ntlm.html
|
||||||
http://www.innovation.ch/java/ntlm.html
|
http://www.innovation.ch/java/ntlm.html
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "http_ntlm.h"
|
#include "http_ntlm.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "http.h" /* for Curl_http_auth_stage() */
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -72,9 +72,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define this to make the type-3 message include the NT response message */
|
/* Define this to make the type-3 message include the NT response message */
|
||||||
#define USE_NTRESPONSES 1
|
#define USE_NTRESPONSES 1
|
||||||
@@ -135,7 +133,7 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
|||||||
memcpy(ntlm->nonce, &buffer[24], 8);
|
memcpy(ntlm->nonce, &buffer[24], 8);
|
||||||
|
|
||||||
/* at index decimal 20, there's a 32bit NTLM flag field */
|
/* at index decimal 20, there's a 32bit NTLM flag field */
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(ntlm->state >= NTLMSTATE_TYPE1)
|
if(ntlm->state >= NTLMSTATE_TYPE1)
|
||||||
@@ -222,7 +220,7 @@ static void mkhash(char *password,
|
|||||||
|
|
||||||
if (len > 14)
|
if (len > 14)
|
||||||
len = 14;
|
len = 14;
|
||||||
|
|
||||||
for (i=0; i<len; i++)
|
for (i=0; i<len; i++)
|
||||||
pw[i] = toupper(password[i]);
|
pw[i] = toupper(password[i]);
|
||||||
|
|
||||||
@@ -236,7 +234,7 @@ static void mkhash(char *password,
|
|||||||
setup_des_key(pw, DESKEY(ks));
|
setup_des_key(pw, DESKEY(ks));
|
||||||
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
|
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
|
||||||
DESKEY(ks), DES_ENCRYPT);
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
|
||||||
setup_des_key(pw+7, DESKEY(ks));
|
setup_des_key(pw+7, DESKEY(ks));
|
||||||
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
|
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
|
||||||
DESKEY(ks), DES_ENCRYPT);
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
@@ -298,23 +296,26 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
char *passwdp;
|
char *passwdp;
|
||||||
/* point to the correct struct with this */
|
/* point to the correct struct with this */
|
||||||
struct ntlmdata *ntlm;
|
struct ntlmdata *ntlm;
|
||||||
|
struct auth *authp;
|
||||||
|
|
||||||
curlassert(conn);
|
curlassert(conn);
|
||||||
curlassert(conn->data);
|
curlassert(conn->data);
|
||||||
conn->data->state.authdone = FALSE;
|
|
||||||
|
|
||||||
if(proxy) {
|
if(proxy) {
|
||||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||||
userp = conn->proxyuser;
|
userp = conn->proxyuser;
|
||||||
passwdp = conn->proxypasswd;
|
passwdp = conn->proxypasswd;
|
||||||
ntlm = &conn->proxyntlm;
|
ntlm = &conn->proxyntlm;
|
||||||
|
authp = &conn->data->state.authproxy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
allocuserpwd = &conn->allocptr.userpwd;
|
allocuserpwd = &conn->allocptr.userpwd;
|
||||||
userp = conn->user;
|
userp = conn->user;
|
||||||
passwdp = conn->passwd;
|
passwdp = conn->passwd;
|
||||||
ntlm = &conn->ntlm;
|
ntlm = &conn->ntlm;
|
||||||
|
authp = &conn->data->state.authhost;
|
||||||
}
|
}
|
||||||
|
authp->done = FALSE;
|
||||||
|
|
||||||
/* not set means empty */
|
/* not set means empty */
|
||||||
if(!userp)
|
if(!userp)
|
||||||
@@ -322,13 +323,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
|
|
||||||
if(!passwdp)
|
if(!passwdp)
|
||||||
passwdp=(char *)"";
|
passwdp=(char *)"";
|
||||||
|
|
||||||
switch(ntlm->state) {
|
switch(ntlm->state) {
|
||||||
case NTLMSTATE_TYPE1:
|
case NTLMSTATE_TYPE1:
|
||||||
default: /* for the weird cases we (re)start here */
|
default: /* for the weird cases we (re)start here */
|
||||||
hostoff = 32;
|
hostoff = 32;
|
||||||
domoff = hostoff + hostlen;
|
domoff = hostoff + hostlen;
|
||||||
|
|
||||||
/* Create and send a type-1 message:
|
/* Create and send a type-1 message:
|
||||||
|
|
||||||
Index Description Content
|
Index Description Content
|
||||||
@@ -390,7 +391,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
|
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NTLMSTATE_TYPE2:
|
case NTLMSTATE_TYPE2:
|
||||||
/* We received the type-2 already, create a type-3 message:
|
/* We received the type-2 already, create a type-3 message:
|
||||||
|
|
||||||
@@ -408,7 +409,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
52 (64) start of data block
|
52 (64) start of data block
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
int lmrespoff;
|
int lmrespoff;
|
||||||
int ntrespoff;
|
int ntrespoff;
|
||||||
@@ -458,25 +459,25 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
"%c%c" /* NT-response allocated space */
|
"%c%c" /* NT-response allocated space */
|
||||||
"%c%c" /* NT-response offset */
|
"%c%c" /* NT-response offset */
|
||||||
"%c%c" /* 2 zeroes */
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
"%c%c" /* domain length */
|
"%c%c" /* domain length */
|
||||||
"%c%c" /* domain allocated space */
|
"%c%c" /* domain allocated space */
|
||||||
"%c%c" /* domain name offset */
|
"%c%c" /* domain name offset */
|
||||||
"%c%c" /* 2 zeroes */
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
"%c%c" /* user length */
|
"%c%c" /* user length */
|
||||||
"%c%c" /* user allocated space */
|
"%c%c" /* user allocated space */
|
||||||
"%c%c" /* user offset */
|
"%c%c" /* user offset */
|
||||||
"%c%c" /* 2 zeroes */
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
"%c%c" /* host length */
|
"%c%c" /* host length */
|
||||||
"%c%c" /* host allocated space */
|
"%c%c" /* host allocated space */
|
||||||
"%c%c" /* host offset */
|
"%c%c" /* host offset */
|
||||||
"%c%c%c%c%c%c" /* 6 zeroes */
|
"%c%c%c%c%c%c" /* 6 zeroes */
|
||||||
|
|
||||||
"\xff\xff" /* message length */
|
"\xff\xff" /* message length */
|
||||||
"%c%c" /* 2 zeroes */
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
"\x01\x82" /* flags */
|
"\x01\x82" /* flags */
|
||||||
"%c%c" /* 2 zeroes */
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
@@ -493,7 +494,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
SHORTPAIR(0x18),
|
SHORTPAIR(0x18),
|
||||||
SHORTPAIR(lmrespoff),
|
SHORTPAIR(lmrespoff),
|
||||||
0x0, 0x0,
|
0x0, 0x0,
|
||||||
|
|
||||||
#ifdef USE_NTRESPONSES
|
#ifdef USE_NTRESPONSES
|
||||||
SHORTPAIR(0x18), /* NT-response length, twice */
|
SHORTPAIR(0x18), /* NT-response length, twice */
|
||||||
SHORTPAIR(0x18),
|
SHORTPAIR(0x18),
|
||||||
@@ -513,12 +514,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
SHORTPAIR(userlen),
|
SHORTPAIR(userlen),
|
||||||
SHORTPAIR(useroff),
|
SHORTPAIR(useroff),
|
||||||
0x0, 0x0,
|
0x0, 0x0,
|
||||||
|
|
||||||
SHORTPAIR(hostlen),
|
SHORTPAIR(hostlen),
|
||||||
SHORTPAIR(hostlen),
|
SHORTPAIR(hostlen),
|
||||||
SHORTPAIR(hostoff),
|
SHORTPAIR(hostoff),
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
|
||||||
0x0, 0x0,
|
0x0, 0x0,
|
||||||
|
|
||||||
0x0, 0x0);
|
0x0, 0x0);
|
||||||
@@ -540,7 +541,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_NTRESPONSES
|
#ifdef USE_NTRESPONSES
|
||||||
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
||||||
memcpy(&ntlmbuf[size], ntresp, 0x18);
|
memcpy(&ntlmbuf[size], ntresp, 0x18);
|
||||||
size += 0x18;
|
size += 0x18;
|
||||||
}
|
}
|
||||||
@@ -563,11 +564,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
|
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
|
||||||
|
|
||||||
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
|
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
|
||||||
conn->data->state.authdone = TRUE;
|
authp->done = TRUE;
|
||||||
|
|
||||||
/* Switch to web authentication after proxy authentication is done */
|
|
||||||
if (proxy)
|
|
||||||
Curl_http_auth_stage(conn->data, 401);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -578,7 +575,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
free(*allocuserpwd);
|
free(*allocuserpwd);
|
||||||
*allocuserpwd=NULL;
|
*allocuserpwd=NULL;
|
||||||
}
|
}
|
||||||
conn->data->state.authdone = TRUE;
|
authp->done = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
lib/if2ip.c
10
lib/if2ip.c
@@ -73,15 +73,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "if2ip.h"
|
#include "if2ip.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SYS_ERROR -1
|
#define SYS_ERROR -1
|
||||||
|
|
||||||
char *Curl_if2ip(char *interface, char *buf, int buf_size)
|
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
int dummy;
|
int dummy;
|
||||||
char *ip=NULL;
|
char *ip=NULL;
|
||||||
@@ -125,8 +124,11 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
|
|||||||
|
|
||||||
/* -- end of if2ip() -- */
|
/* -- end of if2ip() -- */
|
||||||
#else
|
#else
|
||||||
char *Curl_if2ip(char *interface, char *buf, int buf_size)
|
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
|
(void) interface;
|
||||||
|
(void) buf;
|
||||||
|
(void) buf_size;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
|
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
|
||||||
!defined(__riscos__) && !defined(__INTERIX)
|
!defined(__riscos__) && !defined(__INTERIX)
|
||||||
extern char *Curl_if2ip(char *interface, char *buf, int buf_size);
|
extern char *Curl_if2ip(const char *interface, char *buf, int buf_size);
|
||||||
#else
|
#else
|
||||||
#define Curl_if2ip(a,b,c) NULL
|
#define Curl_if2ip(a,b,c) NULL
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
195
lib/inet_ntop.c
Normal file
195
lib/inet_ntop.c
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Original code by Paul Vixie. "curlified" by Gisle Vanem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_NTOP
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
/* this platform has a inet_ntoa_r() function, but no proto declared anywhere
|
||||||
|
so we include our own proto to make compilers happy */
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IN6ADDRSZ 16
|
||||||
|
#define INADDRSZ 4
|
||||||
|
#define INT16SZ 2
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||||
|
#define SET_ERRNO(e) WSASetLastError(errno = (e))
|
||||||
|
#else
|
||||||
|
#define SET_ERRNO(e) errno = e
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format an IPv4 address, more or less like inet_ntoa().
|
||||||
|
*
|
||||||
|
* Returns `dst' (as a const)
|
||||||
|
* Note:
|
||||||
|
* - uses no statics
|
||||||
|
* - takes a u_char* not an in_addr as input
|
||||||
|
*/
|
||||||
|
static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INET_NTOA_R
|
||||||
|
return inet_ntoa_r(*(struct in_addr*)src, dst, size);
|
||||||
|
#else
|
||||||
|
const char *addr = inet_ntoa(*(struct in_addr*)src);
|
||||||
|
|
||||||
|
if (strlen(addr) >= size)
|
||||||
|
{
|
||||||
|
SET_ERRNO(ENOSPC);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return strcpy(dst, addr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
/*
|
||||||
|
* Convert IPv6 binary address into presentation (printable) format.
|
||||||
|
*/
|
||||||
|
static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Note that int32_t and int16_t need only be "at least" large enough
|
||||||
|
* to contain a value of the specified size. On some systems, like
|
||||||
|
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||||
|
* Keep this in mind if you think this function should have been coded
|
||||||
|
* to use pointer overlays. All the world's not a VAX.
|
||||||
|
*/
|
||||||
|
char tmp [sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||||
|
char *tp;
|
||||||
|
struct {
|
||||||
|
long base;
|
||||||
|
long len;
|
||||||
|
} best, cur;
|
||||||
|
u_long words [IN6ADDRSZ / INT16SZ];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Preprocess:
|
||||||
|
* Copy the input (bytewise) array into a wordwise array.
|
||||||
|
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||||
|
*/
|
||||||
|
memset(words, 0, sizeof(words));
|
||||||
|
for (i = 0; i < IN6ADDRSZ; i++)
|
||||||
|
words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||||
|
|
||||||
|
best.base = -1;
|
||||||
|
cur.base = -1;
|
||||||
|
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
|
||||||
|
{
|
||||||
|
if (words[i] == 0)
|
||||||
|
{
|
||||||
|
if (cur.base == -1)
|
||||||
|
cur.base = i, cur.len = 1;
|
||||||
|
else
|
||||||
|
cur.len++;
|
||||||
|
}
|
||||||
|
else if (cur.base != -1)
|
||||||
|
{
|
||||||
|
if (best.base == -1 || cur.len > best.len)
|
||||||
|
best = cur;
|
||||||
|
cur.base = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
|
||||||
|
best = cur;
|
||||||
|
if (best.base != -1 && best.len < 2)
|
||||||
|
best.base = -1;
|
||||||
|
|
||||||
|
/* Format the result.
|
||||||
|
*/
|
||||||
|
tp = tmp;
|
||||||
|
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
|
||||||
|
{
|
||||||
|
/* Are we inside the best run of 0x00's?
|
||||||
|
*/
|
||||||
|
if (best.base != -1 && i >= best.base && i < (best.base + best.len))
|
||||||
|
{
|
||||||
|
if (i == best.base)
|
||||||
|
*tp++ = ':';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we following an initial run of 0x00s or any real hex?
|
||||||
|
*/
|
||||||
|
if (i != 0)
|
||||||
|
*tp++ = ':';
|
||||||
|
|
||||||
|
/* Is this address an encapsulated IPv4?
|
||||||
|
*/
|
||||||
|
if (i == 6 && best.base == 0 &&
|
||||||
|
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
|
||||||
|
{
|
||||||
|
if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
|
||||||
|
{
|
||||||
|
SET_ERRNO(ENOSPC);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
tp += strlen(tp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tp += sprintf (tp, "%lx", words[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Was it a trailing run of 0x00's?
|
||||||
|
*/
|
||||||
|
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
|
||||||
|
*tp++ = ':';
|
||||||
|
*tp++ = '\0';
|
||||||
|
|
||||||
|
/* Check for overflow, copy, and we're done.
|
||||||
|
*/
|
||||||
|
if ((size_t)(tp - tmp) > size)
|
||||||
|
{
|
||||||
|
SET_ERRNO(ENOSPC);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return strcpy (dst, tmp);
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_IPV6 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a network format address to presentation format.
|
||||||
|
*
|
||||||
|
* Returns pointer to presentation format address (`dst'),
|
||||||
|
* Returns NULL on error (see errno).
|
||||||
|
*/
|
||||||
|
const char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
return inet_ntop4((const u_char*)src, buf, size);
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
return inet_ntop6((const u_char*)src, buf, size);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
SET_ERRNO(EAFNOSUPPORT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_INET_NTOP */
|
||||||
37
lib/inet_ntop.h
Normal file
37
lib/inet_ntop.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __INET_NTOP_H
|
||||||
|
#define __INET_NTOP_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_INET_NTOP
|
||||||
|
#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af,addr,buf,size)
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
const char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __INET_NTOP_H */
|
||||||
@@ -60,15 +60,14 @@
|
|||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "krb4.h"
|
#include "krb4.h"
|
||||||
|
#include "memory.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"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOCAL_ADDR (&conn->local_addr)
|
#define LOCAL_ADDR (&conn->local_addr)
|
||||||
#define REMOTE_ADDR (&conn->serv_addr)
|
#define REMOTE_ADDR (&conn->serv_addr)
|
||||||
@@ -206,7 +205,7 @@ 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;
|
||||||
char *host = conn->hostname;
|
char *host = conn->host.name;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int l = sizeof(conn->local_addr);
|
int l = sizeof(conn->local_addr);
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
@@ -375,7 +374,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
|
|||||||
if (strcmp ((char*)tktcopy.dat + 8,
|
if (strcmp ((char*)tktcopy.dat + 8,
|
||||||
KRB_TICKET_GRANTING_TICKET) != 0) {
|
KRB_TICKET_GRANTING_TICKET) != 0) {
|
||||||
afs_string_to_key(passwd,
|
afs_string_to_key(passwd,
|
||||||
krb_realmofhost(conn->hostname),
|
krb_realmofhost(conn->host.name),
|
||||||
&key);
|
&key);
|
||||||
des_key_sched(&key, schedule);
|
des_key_sched(&key, schedule);
|
||||||
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
|
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
|
||||||
|
|||||||
639
lib/ldap.c
639
lib/ldap.c
@@ -1,16 +1,16 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -34,14 +34,18 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(__GNUC__)
|
#if defined(WIN32)
|
||||||
#else
|
# include <windows.h>
|
||||||
# ifdef HAVE_UNISTD_H
|
# include <malloc.h>
|
||||||
# include <unistd.h>
|
# include <WinLdap.h>
|
||||||
# endif
|
#endif
|
||||||
# ifdef HAVE_DLFCN_H
|
|
||||||
# include <dlfcn.h>
|
#ifdef HAVE_UNISTD_H
|
||||||
# endif
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DLFCN_H
|
||||||
|
# include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
@@ -49,25 +53,62 @@
|
|||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "transfer.h"
|
#include "transfer.h"
|
||||||
|
#include "strequal.h"
|
||||||
|
#include "strtok.h"
|
||||||
#include "ldap.h"
|
#include "ldap.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
typedef void * (*dynafunc)(void *input);
|
#include "memdebug.h"
|
||||||
|
|
||||||
#define DYNA_GET_FUNCTION(type, fnc) \
|
/* WLdap32.dll functions are *not* stdcall. Must call these via __cdecl
|
||||||
(fnc) = (type)DynaGetFunction(#fnc); \
|
* pointers in case libcurl was compiled as fastcall (-Gr).
|
||||||
if ((fnc) == NULL) { \
|
*/
|
||||||
return CURLE_FUNCTION_NOT_FOUND; \
|
#if !defined(WIN32) && !defined(__cdecl)
|
||||||
}
|
#define __cdecl
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LDAP_SIZELIMIT_EXCEEDED
|
||||||
|
#define LDAP_SIZELIMIT_EXCEEDED 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DLOPEN_MODE RTLD_LAZY /*! assume all dlopen() implementations have
|
||||||
|
this */
|
||||||
|
|
||||||
|
#if defined(RTLD_LAZY_GLOBAL) /* It turns out some systems use this: */
|
||||||
|
# undef DLOPEN_MODE
|
||||||
|
# define DLOPEN_MODE RTLD_LAZY_GLOBAL
|
||||||
|
#elif defined(RTLD_GLOBAL)
|
||||||
|
# undef DLOPEN_MODE
|
||||||
|
# define DLOPEN_MODE (RTLD_LAZY | RTLD_GLOBAL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DYNA_GET_FUNCTION(type, fnc) do { \
|
||||||
|
(fnc) = (type)DynaGetFunction(#fnc); \
|
||||||
|
if ((fnc) == NULL) \
|
||||||
|
return CURLE_FUNCTION_NOT_FOUND; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*! CygWin etc. configure could set these, but we don't want it.
|
||||||
|
* Must use WLdap32.dll code.
|
||||||
|
*/
|
||||||
|
#if defined(WIN32)
|
||||||
|
#undef HAVE_DLOPEN
|
||||||
|
#undef HAVE_LIBDL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void * (*dynafunc)(void *input);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*/
|
*/
|
||||||
static void *libldap = NULL;
|
static void *libldap = NULL;
|
||||||
|
#ifndef WIN32
|
||||||
static void *liblber = NULL;
|
static void *liblber = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void DynaOpen(void)
|
static int DynaOpen(const char **mod_name)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
|
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
|
||||||
if (libldap == NULL) {
|
if (libldap == NULL) {
|
||||||
@@ -76,20 +117,26 @@ static void DynaOpen(void)
|
|||||||
* liblber.so automatically, but since it does not we will
|
* liblber.so automatically, but since it does not we will
|
||||||
* handle it here by opening liblber.so as global.
|
* handle it here by opening liblber.so as global.
|
||||||
*/
|
*/
|
||||||
liblber = dlopen("liblber.so",
|
*mod_name = "liblber.so";
|
||||||
#ifdef RTLD_LAZY_GLOBAL /* It turns out some systems use this: */
|
liblber = dlopen(*mod_name, DLOPEN_MODE);
|
||||||
RTLD_LAZY_GLOBAL
|
|
||||||
#else
|
/* Assume loading libldap.so will fail if loading of liblber.so failed
|
||||||
#ifdef RTLD_GLOBAL
|
*/
|
||||||
RTLD_LAZY | RTLD_GLOBAL
|
if (liblber) {
|
||||||
#else
|
*mod_name = "libldap.so";
|
||||||
/* and some systems don't have the RTLD_GLOBAL symbol */
|
libldap = dlopen(*mod_name, RTLD_LAZY);
|
||||||
RTLD_LAZY
|
}
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
libldap = dlopen("libldap.so", RTLD_LAZY);
|
|
||||||
}
|
}
|
||||||
|
return (libldap != NULL && liblber != NULL);
|
||||||
|
|
||||||
|
#elif defined(WIN32)
|
||||||
|
*mod_name = "wldap32.dll";
|
||||||
|
if (!libldap)
|
||||||
|
libldap = (void*)LoadLibrary(*mod_name);
|
||||||
|
return (libldap != NULL);
|
||||||
|
|
||||||
|
#else
|
||||||
|
return (0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +151,11 @@ static void DynaClose(void)
|
|||||||
dlclose(liblber);
|
dlclose(liblber);
|
||||||
liblber=NULL;
|
liblber=NULL;
|
||||||
}
|
}
|
||||||
|
#elif defined(WIN32)
|
||||||
|
if (libldap) {
|
||||||
|
FreeLibrary ((HMODULE)libldap);
|
||||||
|
libldap = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,65 +165,91 @@ static dynafunc DynaGetFunction(const char *name)
|
|||||||
|
|
||||||
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
|
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
|
||||||
if (libldap) {
|
if (libldap) {
|
||||||
func = (dynafunc) dlsym(libldap, name);
|
/* This typecast magic below was brought by Joe Halpin. In ISO C, you
|
||||||
|
* cannot typecast a data pointer to a function pointer, but that's
|
||||||
|
* exactly what we need to do here to avoid compiler warnings on picky
|
||||||
|
* compilers! */
|
||||||
|
*(void**) (&func) = dlsym(libldap, name);
|
||||||
|
}
|
||||||
|
#elif defined(WIN32)
|
||||||
|
if (libldap) {
|
||||||
|
func = (dynafunc)GetProcAddress((HINSTANCE)libldap, name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*/
|
*/
|
||||||
typedef struct ldap_url_desc {
|
typedef struct ldap_url_desc {
|
||||||
struct ldap_url_desc *lud_next;
|
struct ldap_url_desc *lud_next;
|
||||||
char *lud_scheme;
|
char *lud_scheme;
|
||||||
char *lud_host;
|
char *lud_host;
|
||||||
int lud_port;
|
int lud_port;
|
||||||
char *lud_dn;
|
char *lud_dn;
|
||||||
char **lud_attrs;
|
char **lud_attrs;
|
||||||
int lud_scope;
|
int lud_scope;
|
||||||
char *lud_filter;
|
char *lud_filter;
|
||||||
char **lud_exts;
|
char **lud_exts;
|
||||||
int lud_crit_exts;
|
int lud_crit_exts;
|
||||||
} LDAPURLDesc;
|
} LDAPURLDesc;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static int _ldap_url_parse (const struct connectdata *conn,
|
||||||
|
LDAPURLDesc **ludp);
|
||||||
|
static void _ldap_free_urldesc (LDAPURLDesc *ludp);
|
||||||
|
|
||||||
|
static void (*ldap_free_urldesc)(LDAPURLDesc *) = _ldap_free_urldesc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_LDAP
|
||||||
|
#define LDAP_TRACE(x) do { \
|
||||||
|
_ldap_trace ("%u: ", __LINE__); \
|
||||||
|
_ldap_trace x; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void _ldap_trace (const char *fmt, ...);
|
||||||
|
#else
|
||||||
|
#define LDAP_TRACE(x) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CURLcode Curl_ldap(struct connectdata *conn)
|
CURLcode Curl_ldap(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode status = CURLE_OK;
|
CURLcode status = CURLE_OK;
|
||||||
int rc;
|
int rc = 0;
|
||||||
void *(*ldap_init)(char *, int);
|
#ifndef WIN32
|
||||||
int (*ldap_simple_bind_s)(void *, char *, char *);
|
int (*ldap_url_parse)(char *, LDAPURLDesc **);
|
||||||
int (*ldap_unbind_s)(void *);
|
void (*ldap_free_urldesc)(void *);
|
||||||
int (*ldap_url_parse)(char *, LDAPURLDesc **);
|
#endif
|
||||||
void (*ldap_free_urldesc)(void *);
|
void *(__cdecl *ldap_init)(char *, int);
|
||||||
int (*ldap_search_s)(void *, char *, int, char *, char **, int, void **);
|
int (__cdecl *ldap_simple_bind_s)(void *, char *, char *);
|
||||||
int (*ldap_search_st)(void *, char *, int, char *, char **, int, void *, void **);
|
int (__cdecl *ldap_unbind_s)(void *);
|
||||||
void *(*ldap_first_entry)(void *, void *);
|
int (__cdecl *ldap_search_s)(void *, char *, int, char *, char **,
|
||||||
void *(*ldap_next_entry)(void *, void *);
|
int, void **);
|
||||||
char *(*ldap_err2string)(int);
|
void *(__cdecl *ldap_first_entry)(void *, void *);
|
||||||
char *(*ldap_get_dn)(void *, void *);
|
void *(__cdecl *ldap_next_entry)(void *, void *);
|
||||||
char *(*ldap_first_attribute)(void *, void *, void **);
|
char *(__cdecl *ldap_err2string)(int);
|
||||||
char *(*ldap_next_attribute)(void *, void *, void *);
|
char *(__cdecl *ldap_get_dn)(void *, void *);
|
||||||
char **(*ldap_get_values)(void *, void *, char *);
|
char *(__cdecl *ldap_first_attribute)(void *, void *, void **);
|
||||||
void (*ldap_value_free)(char **);
|
char *(__cdecl *ldap_next_attribute)(void *, void *, void *);
|
||||||
void (*ldap_memfree)(void *);
|
char **(__cdecl *ldap_get_values)(void *, void *, const char *);
|
||||||
void (*ber_free)(void *, int);
|
void (__cdecl *ldap_value_free)(char **);
|
||||||
|
void (__cdecl *ldap_memfree)(void *);
|
||||||
|
void (__cdecl *ber_free)(void *, int);
|
||||||
|
|
||||||
void *server;
|
void *server;
|
||||||
LDAPURLDesc *ludp;
|
LDAPURLDesc *ludp = NULL;
|
||||||
|
const char *mod_name;
|
||||||
void *result;
|
void *result;
|
||||||
void *entryIterator;
|
void *entryIterator; /*! type should be 'LDAPMessage *' */
|
||||||
void *ber;
|
int num = 0;
|
||||||
void *attribute;
|
|
||||||
|
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
|
|
||||||
infof(data, "LDAP: %s\n", data->change.url);
|
|
||||||
|
|
||||||
DynaOpen();
|
infof(data, "LDAP local: %s\n", data->change.url);
|
||||||
if (libldap == NULL) {
|
|
||||||
failf(data, "The needed LDAP library/libraries couldn't be opened");
|
if (!DynaOpen(&mod_name)) {
|
||||||
|
failf(data, "The %s LDAP library/libraries couldn't be opened", mod_name);
|
||||||
return CURLE_LIBRARY_NOT_FOUND;
|
return CURLE_LIBRARY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,96 +259,367 @@ CURLcode Curl_ldap(struct connectdata *conn)
|
|||||||
DYNA_GET_FUNCTION(void *(*)(char *, int), ldap_init);
|
DYNA_GET_FUNCTION(void *(*)(char *, int), ldap_init);
|
||||||
DYNA_GET_FUNCTION(int (*)(void *, char *, char *), ldap_simple_bind_s);
|
DYNA_GET_FUNCTION(int (*)(void *, char *, char *), ldap_simple_bind_s);
|
||||||
DYNA_GET_FUNCTION(int (*)(void *), ldap_unbind_s);
|
DYNA_GET_FUNCTION(int (*)(void *), ldap_unbind_s);
|
||||||
|
#ifndef WIN32
|
||||||
DYNA_GET_FUNCTION(int (*)(char *, LDAPURLDesc **), ldap_url_parse);
|
DYNA_GET_FUNCTION(int (*)(char *, LDAPURLDesc **), ldap_url_parse);
|
||||||
DYNA_GET_FUNCTION(void (*)(void *), ldap_free_urldesc);
|
DYNA_GET_FUNCTION(void (*)(void *), ldap_free_urldesc);
|
||||||
DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int, void **), ldap_search_s);
|
#endif
|
||||||
DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int, void *, void **), ldap_search_st);
|
DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int,
|
||||||
|
void **), ldap_search_s);
|
||||||
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_first_entry);
|
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_first_entry);
|
||||||
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_next_entry);
|
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_next_entry);
|
||||||
DYNA_GET_FUNCTION(char *(*)(int), ldap_err2string);
|
DYNA_GET_FUNCTION(char *(*)(int), ldap_err2string);
|
||||||
DYNA_GET_FUNCTION(char *(*)(void *, void *), ldap_get_dn);
|
DYNA_GET_FUNCTION(char *(*)(void *, void *), ldap_get_dn);
|
||||||
DYNA_GET_FUNCTION(char *(*)(void *, void *, void **), ldap_first_attribute);
|
DYNA_GET_FUNCTION(char *(*)(void *, void *, void **), ldap_first_attribute);
|
||||||
DYNA_GET_FUNCTION(char *(*)(void *, void *, void *), ldap_next_attribute);
|
DYNA_GET_FUNCTION(char *(*)(void *, void *, void *), ldap_next_attribute);
|
||||||
DYNA_GET_FUNCTION(char **(*)(void *, void *, char *), ldap_get_values);
|
DYNA_GET_FUNCTION(char **(*)(void *, void *, const char *), ldap_get_values);
|
||||||
DYNA_GET_FUNCTION(void (*)(char **), ldap_value_free);
|
DYNA_GET_FUNCTION(void (*)(char **), ldap_value_free);
|
||||||
DYNA_GET_FUNCTION(void (*)(void *), ldap_memfree);
|
DYNA_GET_FUNCTION(void (*)(void *), ldap_memfree);
|
||||||
DYNA_GET_FUNCTION(void (*)(void *, int), ber_free);
|
DYNA_GET_FUNCTION(void (*)(void *, int), ber_free);
|
||||||
|
|
||||||
server = ldap_init(conn->hostname, conn->port);
|
server = (*ldap_init)(conn->host.name, conn->port);
|
||||||
if (server == NULL) {
|
if (server == NULL) {
|
||||||
failf(data, "LDAP: Cannot connect to %s:%d",
|
failf(data, "LDAP local: Cannot connect to %s:%d",
|
||||||
conn->hostname, conn->port);
|
conn->host.name, conn->port);
|
||||||
status = CURLE_COULDNT_CONNECT;
|
status = CURLE_COULDNT_CONNECT;
|
||||||
|
goto quit;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
rc = ldap_simple_bind_s(server,
|
|
||||||
conn->bits.user_passwd?conn->user:NULL,
|
|
||||||
conn->bits.user_passwd?conn->passwd:NULL);
|
|
||||||
if (rc != 0) {
|
|
||||||
failf(data, "LDAP: %s", ldap_err2string(rc));
|
|
||||||
status = CURLE_LDAP_CANNOT_BIND;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rc = ldap_url_parse(data->change.url, &ludp);
|
|
||||||
if (rc != 0) {
|
|
||||||
failf(data, "LDAP: %s", ldap_err2string(rc));
|
|
||||||
status = CURLE_LDAP_INVALID_URL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
|
|
||||||
ludp->lud_filter, ludp->lud_attrs, 0, &result);
|
|
||||||
if (rc != 0) {
|
|
||||||
failf(data, "LDAP: %s", ldap_err2string(rc));
|
|
||||||
status = CURLE_LDAP_SEARCH_FAILED;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (entryIterator = ldap_first_entry(server, result);
|
|
||||||
entryIterator;
|
|
||||||
entryIterator = ldap_next_entry(server, entryIterator)) {
|
|
||||||
char *dn = ldap_get_dn(server, entryIterator);
|
|
||||||
char **vals;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, dn, 0);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
|
||||||
for(attribute = ldap_first_attribute(server, entryIterator,
|
|
||||||
&ber);
|
|
||||||
attribute;
|
|
||||||
attribute = ldap_next_attribute(server, entryIterator,
|
|
||||||
ber) ) {
|
|
||||||
vals = ldap_get_values(server, entryIterator, attribute);
|
|
||||||
if (vals != NULL) {
|
|
||||||
for(i = 0; (vals[i] != NULL); i++) {
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char*)"\t", 1);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, attribute, 0);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, vals[i], 0);
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free memory used to store values */
|
rc = (*ldap_simple_bind_s)(server,
|
||||||
ldap_value_free(vals);
|
conn->bits.user_passwd ? conn->user : NULL,
|
||||||
}
|
conn->bits.user_passwd ? conn->passwd : NULL);
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
if (rc != 0) {
|
||||||
|
failf(data, "LDAP local: %s", (*ldap_err2string)(rc));
|
||||||
ldap_memfree(attribute);
|
status = CURLE_LDAP_CANNOT_BIND;
|
||||||
ldap_memfree(dn);
|
goto quit;
|
||||||
if (ber) ber_free(ber, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ldap_free_urldesc(ludp);
|
|
||||||
}
|
|
||||||
ldap_unbind_s(server);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
rc = _ldap_url_parse(conn, &ludp);
|
||||||
|
#else
|
||||||
|
rc = (*ldap_url_parse)(data->change.url, &ludp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
failf(data, "LDAP local: %s", (*ldap_err2string)(rc));
|
||||||
|
status = CURLE_LDAP_INVALID_URL;
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = (*ldap_search_s)(server, ludp->lud_dn, ludp->lud_scope,
|
||||||
|
ludp->lud_filter, ludp->lud_attrs, 0, &result);
|
||||||
|
|
||||||
|
if (rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
|
||||||
|
failf(data, "LDAP remote: %s", (*ldap_err2string)(rc));
|
||||||
|
status = CURLE_LDAP_SEARCH_FAILED;
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(num = 0, entryIterator = (*ldap_first_entry)(server, result);
|
||||||
|
entryIterator;
|
||||||
|
entryIterator = (*ldap_next_entry)(server, entryIterator), num++)
|
||||||
|
{
|
||||||
|
void *ber = NULL; /*! is really 'BerElement **' */
|
||||||
|
void *attribute; /*! suspicious that this isn't 'const' */
|
||||||
|
char *dn = (*ldap_get_dn)(server, entryIterator);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)dn, 0);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
||||||
|
|
||||||
|
for (attribute = (*ldap_first_attribute)(server, entryIterator, &ber);
|
||||||
|
attribute;
|
||||||
|
attribute = (*ldap_next_attribute)(server, entryIterator, ber))
|
||||||
|
{
|
||||||
|
char **vals = (*ldap_get_values)(server, entryIterator, attribute);
|
||||||
|
|
||||||
|
if (vals != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; (vals[i] != NULL); i++)
|
||||||
|
{
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char*) attribute, 0);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, vals[i], 0);
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free memory used to store values */
|
||||||
|
(*ldap_value_free)(vals);
|
||||||
|
}
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
||||||
|
|
||||||
|
(*ldap_memfree)(attribute);
|
||||||
|
(*ldap_memfree)(dn);
|
||||||
|
}
|
||||||
|
if (ber)
|
||||||
|
(*ber_free)(ber, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
quit:
|
||||||
|
LDAP_TRACE (("Received %d entries\n", num));
|
||||||
|
if (rc == LDAP_SIZELIMIT_EXCEEDED)
|
||||||
|
infof(data, "There are more than %d entries\n", num);
|
||||||
|
if (ludp)
|
||||||
|
(*ldap_free_urldesc)(ludp);
|
||||||
|
if (server)
|
||||||
|
(*ldap_unbind_s)(server);
|
||||||
|
|
||||||
DynaClose();
|
DynaClose();
|
||||||
|
|
||||||
/* no data to transfer */
|
/* no data to transfer */
|
||||||
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_LDAP
|
||||||
|
static void _ldap_trace (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static int do_trace = -1;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (do_trace == -1) {
|
||||||
|
const char *env = getenv("CURL_TRACE");
|
||||||
|
do_trace = (env && atoi(env) > 0);
|
||||||
|
}
|
||||||
|
if (!do_trace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start (args, fmt);
|
||||||
|
vfprintf (stderr, fmt, args);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/*
|
||||||
|
* Return scope-value for a scope-string.
|
||||||
|
*/
|
||||||
|
static int str2scope (const char *p)
|
||||||
|
{
|
||||||
|
if (!stricmp(p, "one"))
|
||||||
|
return LDAP_SCOPE_ONELEVEL;
|
||||||
|
if (!stricmp(p, "onetree"))
|
||||||
|
return LDAP_SCOPE_ONELEVEL;
|
||||||
|
if (!stricmp(p, "base"))
|
||||||
|
return LDAP_SCOPE_BASE;
|
||||||
|
if (!stricmp(p, "sub"))
|
||||||
|
return LDAP_SCOPE_SUBTREE;
|
||||||
|
if (!stricmp( p, "subtree"))
|
||||||
|
return LDAP_SCOPE_SUBTREE;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split 'str' into strings separated by commas.
|
||||||
|
* Note: res[] points into 'str'.
|
||||||
|
*/
|
||||||
|
static char **split_str (char *str)
|
||||||
|
{
|
||||||
|
char **res, *lasts, *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 2, s = strchr(str,','); s; i++)
|
||||||
|
s = strchr(++s,',');
|
||||||
|
|
||||||
|
res = calloc(i, sizeof(char*));
|
||||||
|
if (!res)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0, s = strtok_r(str, ",", &lasts); s;
|
||||||
|
s = strtok_r(NULL, ",", &lasts), i++)
|
||||||
|
res[i] = s;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unescape the LDAP-URL components
|
||||||
|
*/
|
||||||
|
static bool unescape_elements (LDAPURLDesc *ludp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ludp->lud_filter) {
|
||||||
|
ludp->lud_filter = curl_unescape(ludp->lud_filter, 0);
|
||||||
|
if (!ludp->lud_filter)
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
|
||||||
|
ludp->lud_attrs[i] = curl_unescape(ludp->lud_attrs[i], 0);
|
||||||
|
if (!ludp->lud_attrs[i])
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
|
||||||
|
ludp->lud_exts[i] = curl_unescape(ludp->lud_exts[i], 0);
|
||||||
|
if (!ludp->lud_exts[i])
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ludp->lud_dn) {
|
||||||
|
char *dn = ludp->lud_dn;
|
||||||
|
char *new_dn = curl_unescape(dn, 0);
|
||||||
|
|
||||||
|
free(dn);
|
||||||
|
if (!new_dn)
|
||||||
|
return (FALSE);
|
||||||
|
ludp->lud_dn = new_dn;
|
||||||
|
}
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Break apart the pieces of an LDAP URL.
|
||||||
|
* Syntax:
|
||||||
|
* ldap://<hostname>:<port>/<base_dn>?<attributes>?<scope>?<filter>?<ext>
|
||||||
|
*
|
||||||
|
* <hostname> already known from 'conn->host.name'.
|
||||||
|
* <port> already known from 'conn->remote_port'.
|
||||||
|
* extract the rest from 'conn->path+1'. All fields are optional. e.g.
|
||||||
|
* ldap://<hostname>:<port>/?<attributes>?<scope>?<filter> yields ludp->lud_dn = "".
|
||||||
|
*
|
||||||
|
* Ref. http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm#2831915
|
||||||
|
*/
|
||||||
|
static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||||
|
{
|
||||||
|
char *p, *q;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!conn->path || conn->path[0] != '/' ||
|
||||||
|
!checkprefix(conn->protostr, conn->data->change.url))
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
|
||||||
|
ludp->lud_scope = LDAP_SCOPE_BASE;
|
||||||
|
ludp->lud_port = conn->remote_port;
|
||||||
|
ludp->lud_host = conn->host.name;
|
||||||
|
|
||||||
|
/* parse DN (Distinguished Name).
|
||||||
|
*/
|
||||||
|
ludp->lud_dn = strdup(conn->path+1);
|
||||||
|
if (!ludp->lud_dn)
|
||||||
|
return LDAP_NO_MEMORY;
|
||||||
|
|
||||||
|
p = strchr(ludp->lud_dn, '?');
|
||||||
|
LDAP_TRACE (("DN '%.*s'\n", p ? (size_t)(p-ludp->lud_dn) : strlen(ludp->lud_dn),
|
||||||
|
ludp->lud_dn));
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
goto success;
|
||||||
|
|
||||||
|
*p++ = '\0';
|
||||||
|
|
||||||
|
/* parse attributes. skip "??".
|
||||||
|
*/
|
||||||
|
q = strchr(p, '?');
|
||||||
|
if (q)
|
||||||
|
*q++ = '\0';
|
||||||
|
|
||||||
|
if (*p && *p != '?') {
|
||||||
|
ludp->lud_attrs = split_str(p);
|
||||||
|
if (!ludp->lud_attrs)
|
||||||
|
return LDAP_NO_MEMORY;
|
||||||
|
|
||||||
|
for (i = 0; ludp->lud_attrs[i]; i++)
|
||||||
|
LDAP_TRACE (("attr[%d] '%s'\n", i, ludp->lud_attrs[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
p = q;
|
||||||
|
if (!p)
|
||||||
|
goto success;
|
||||||
|
|
||||||
|
/* parse scope. skip "??"
|
||||||
|
*/
|
||||||
|
q = strchr(p, '?');
|
||||||
|
if (q)
|
||||||
|
*q++ = '\0';
|
||||||
|
|
||||||
|
if (*p && *p != '?') {
|
||||||
|
ludp->lud_scope = str2scope(p);
|
||||||
|
if (ludp->lud_scope == -1)
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
LDAP_TRACE (("scope %d\n", ludp->lud_scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
p = q;
|
||||||
|
if (!p)
|
||||||
|
goto success;
|
||||||
|
|
||||||
|
/* parse filter
|
||||||
|
*/
|
||||||
|
q = strchr(p, '?');
|
||||||
|
if (q)
|
||||||
|
*q++ = '\0';
|
||||||
|
if (!*p)
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
|
||||||
|
ludp->lud_filter = p;
|
||||||
|
LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
|
||||||
|
|
||||||
|
p = q;
|
||||||
|
if (!p)
|
||||||
|
goto success;
|
||||||
|
|
||||||
|
/* parse extensions
|
||||||
|
*/
|
||||||
|
ludp->lud_exts = split_str(p);
|
||||||
|
if (!ludp->lud_exts)
|
||||||
|
return LDAP_NO_MEMORY;
|
||||||
|
|
||||||
|
for (i = 0; ludp->lud_exts[i]; i++)
|
||||||
|
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
|
||||||
|
|
||||||
|
success:
|
||||||
|
if (!unescape_elements(ludp))
|
||||||
|
return LDAP_NO_MEMORY;
|
||||||
|
return LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ldap_url_parse (const struct connectdata *conn,
|
||||||
|
LDAPURLDesc **ludpp)
|
||||||
|
{
|
||||||
|
LDAPURLDesc *ludp = calloc(sizeof(*ludp), 1);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
*ludpp = NULL;
|
||||||
|
if (!ludp)
|
||||||
|
return LDAP_NO_MEMORY;
|
||||||
|
|
||||||
|
rc = _ldap_url_parse2 (conn, ludp);
|
||||||
|
if (rc != LDAP_SUCCESS) {
|
||||||
|
_ldap_free_urldesc(ludp);
|
||||||
|
ludp = NULL;
|
||||||
|
}
|
||||||
|
*ludpp = ludp;
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ludp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ludp->lud_dn)
|
||||||
|
free(ludp->lud_dn);
|
||||||
|
|
||||||
|
if (ludp->lud_filter)
|
||||||
|
free(ludp->lud_filter);
|
||||||
|
|
||||||
|
if (ludp->lud_attrs) {
|
||||||
|
for (i = 0; ludp->lud_attrs[i]; i++)
|
||||||
|
free(ludp->lud_attrs[i]);
|
||||||
|
free(ludp->lud_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ludp->lud_exts) {
|
||||||
|
for (i = 0; ludp->lud_exts[i]; i++)
|
||||||
|
free(ludp->lud_exts[i]);
|
||||||
|
free(ludp->lud_exts);
|
||||||
|
}
|
||||||
|
free (ludp);
|
||||||
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
#endif /* CURL_DISABLE_LDAP */
|
||||||
|
|||||||
@@ -25,6 +25,5 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#ifndef CURL_DISABLE_LDAP
|
#ifndef CURL_DISABLE_LDAP
|
||||||
CURLcode Curl_ldap(struct connectdata *conn);
|
CURLcode Curl_ldap(struct connectdata *conn);
|
||||||
CURLcode Curl_ldap_done(struct connectdata *conn);
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* __LDAP_H */
|
#endif /* __LDAP_H */
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ EXPORTS
|
|||||||
curl_easy_setopt @ 5 ;
|
curl_easy_setopt @ 5 ;
|
||||||
curl_escape @ 6 ;
|
curl_escape @ 6 ;
|
||||||
curl_unescape @ 7;
|
curl_unescape @ 7;
|
||||||
curl_formparse @ 8 ;
|
|
||||||
curl_formfree @ 9 ;
|
curl_formfree @ 9 ;
|
||||||
curl_getdate @ 10 ;
|
curl_getdate @ 10 ;
|
||||||
curl_getenv @ 11 ;
|
curl_getenv @ 11 ;
|
||||||
@@ -45,3 +44,7 @@ EXPORTS
|
|||||||
curl_share_init @ 36;
|
curl_share_init @ 36;
|
||||||
curl_share_setopt @ 37;
|
curl_share_setopt @ 37;
|
||||||
curl_share_cleanup @ 38;
|
curl_share_cleanup @ 38;
|
||||||
|
curl_global_init_mem @ 39;
|
||||||
|
curl_easy_strerror @ 40;
|
||||||
|
curl_multi_strerror @ 41;
|
||||||
|
curl_share_strerror @ 42;
|
||||||
|
|||||||
19
lib/llist.c
19
lib/llist.c
@@ -27,11 +27,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "llist.h"
|
#include "llist.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#ifdef CURLDEBUG
|
|
||||||
/* this must be the last include file */
|
/* this must be the last include file */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
void
|
void
|
||||||
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
|
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
|
||||||
{
|
{
|
||||||
@@ -55,24 +55,31 @@ Curl_llist_alloc(curl_llist_dtor dtor)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_llist_insert_next() returns 1 on success and 0 on failure.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
|
Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
|
||||||
{
|
{
|
||||||
curl_llist_element *ne;
|
curl_llist_element *ne =
|
||||||
|
(curl_llist_element *) malloc(sizeof(curl_llist_element));
|
||||||
|
if(!ne)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
|
|
||||||
ne->ptr = (void *) p;
|
ne->ptr = (void *) p;
|
||||||
if (list->size == 0) {
|
if (list->size == 0) {
|
||||||
list->head = ne;
|
list->head = ne;
|
||||||
list->head->prev = NULL;
|
list->head->prev = NULL;
|
||||||
list->head->next = NULL;
|
list->head->next = NULL;
|
||||||
list->tail = ne;
|
list->tail = ne;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ne->next = e->next;
|
ne->next = e->next;
|
||||||
ne->prev = e;
|
ne->prev = e;
|
||||||
if (e->next) {
|
if (e->next) {
|
||||||
e->next->prev = ne;
|
e->next->prev = ne;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
list->tail = ne;
|
list->tail = ne;
|
||||||
}
|
}
|
||||||
e->next = ne;
|
e->next = ne;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
|
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
|
||||||
|
#include "memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
struct memdebug {
|
struct memdebug {
|
||||||
@@ -91,6 +92,9 @@ static bool countcheck(const char *func, int line, const char *source)
|
|||||||
if(logfile && source)
|
if(logfile && source)
|
||||||
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
|
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
|
||||||
source, line, func);
|
source, line, func);
|
||||||
|
if(source)
|
||||||
|
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
|
||||||
|
source, line, func);
|
||||||
return TRUE; /* RETURN ERROR! */
|
return TRUE; /* RETURN ERROR! */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -117,7 +121,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
|
|||||||
/* alloc at least 64 bytes */
|
/* alloc at least 64 bytes */
|
||||||
size = sizeof(struct memdebug)+wantedsize;
|
size = sizeof(struct memdebug)+wantedsize;
|
||||||
|
|
||||||
mem=(struct memdebug *)(malloc)(size);
|
mem=(struct memdebug *)(Curl_cmalloc)(size);
|
||||||
if(mem) {
|
if(mem) {
|
||||||
/* fill memory with junk */
|
/* fill memory with junk */
|
||||||
memset(mem->mem, 0xA5, wantedsize);
|
memset(mem->mem, 0xA5, wantedsize);
|
||||||
@@ -126,8 +130,8 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
|
|||||||
|
|
||||||
if(logfile && source)
|
if(logfile && source)
|
||||||
fprintf(logfile, "MEM %s:%d malloc(%zd) = %p\n",
|
fprintf(logfile, "MEM %s:%d malloc(%zd) = %p\n",
|
||||||
source, line, wantedsize, mem->mem);
|
source, line, wantedsize, mem ? mem->mem : 0);
|
||||||
return mem->mem;
|
return (mem ? mem->mem : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
||||||
@@ -143,7 +147,7 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
|||||||
user_size = wanted_size * wanted_elements;
|
user_size = wanted_size * wanted_elements;
|
||||||
size = sizeof(struct memdebug) + user_size;
|
size = sizeof(struct memdebug) + user_size;
|
||||||
|
|
||||||
mem = (struct memdebug *)(malloc)(size);
|
mem = (struct memdebug *)(Curl_cmalloc)(size);
|
||||||
if(mem) {
|
if(mem) {
|
||||||
/* fill memory with zeroes */
|
/* fill memory with zeroes */
|
||||||
memset(mem->mem, 0, user_size);
|
memset(mem->mem, 0, user_size);
|
||||||
@@ -152,8 +156,8 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
|||||||
|
|
||||||
if(logfile && source)
|
if(logfile && source)
|
||||||
fprintf(logfile, "MEM %s:%d calloc(%u,%u) = %p\n",
|
fprintf(logfile, "MEM %s:%d calloc(%u,%u) = %p\n",
|
||||||
source, line, wanted_elements, wanted_size, mem->mem);
|
source, line, wanted_elements, wanted_size, mem ? mem->mem : 0);
|
||||||
return mem->mem;
|
return (mem ? mem->mem : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *curl_dostrdup(const char *str, int line, const char *source)
|
char *curl_dostrdup(const char *str, int line, const char *source)
|
||||||
@@ -169,6 +173,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
|||||||
len=strlen(str)+1;
|
len=strlen(str)+1;
|
||||||
|
|
||||||
mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
|
mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
|
||||||
|
if (mem)
|
||||||
memcpy(mem, str, len);
|
memcpy(mem, str, len);
|
||||||
|
|
||||||
if(logfile)
|
if(logfile)
|
||||||
@@ -193,7 +198,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
|
|||||||
if(ptr)
|
if(ptr)
|
||||||
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
|
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
|
||||||
|
|
||||||
mem=(struct memdebug *)(realloc)(mem, size);
|
mem=(struct memdebug *)(Curl_crealloc)(mem, size);
|
||||||
if(logfile)
|
if(logfile)
|
||||||
fprintf(logfile, "MEM %s:%d realloc(0x%x, %zd) = %p\n",
|
fprintf(logfile, "MEM %s:%d realloc(0x%x, %zd) = %p\n",
|
||||||
source, line, ptr, wantedsize, mem?mem->mem:NULL);
|
source, line, ptr, wantedsize, mem?mem->mem:NULL);
|
||||||
@@ -218,7 +223,7 @@ void curl_dofree(void *ptr, int line, const char *source)
|
|||||||
memset(mem->mem, 0x13, mem->size);
|
memset(mem->mem, 0x13, mem->size);
|
||||||
|
|
||||||
/* free for real */
|
/* free for real */
|
||||||
(free)(mem);
|
(Curl_cfree)(mem);
|
||||||
|
|
||||||
if(logfile)
|
if(logfile)
|
||||||
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
|
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
|
||||||
|
|||||||
@@ -84,9 +84,12 @@ int curl_fclose(FILE *file, int line, const char *source);
|
|||||||
curl_accept(sock,addr,len,__LINE__,__FILE__)
|
curl_accept(sock,addr,len,__LINE__,__FILE__)
|
||||||
|
|
||||||
#define getaddrinfo(host,serv,hint,res) \
|
#define getaddrinfo(host,serv,hint,res) \
|
||||||
curl_getaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
|
curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
|
||||||
|
#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
|
||||||
|
curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
|
||||||
|
__FILE__)
|
||||||
#define freeaddrinfo(data) \
|
#define freeaddrinfo(data) \
|
||||||
curl_freeaddrinfo(data,__LINE__,__FILE__)
|
curl_dofreeaddrinfo(data,__LINE__,__FILE__)
|
||||||
|
|
||||||
/* sclose is probably already defined, redefine it! */
|
/* sclose is probably already defined, redefine it! */
|
||||||
#undef sclose
|
#undef sclose
|
||||||
|
|||||||
50
lib/memory.h
Normal file
50
lib/memory.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef _CURL_MEMORY_H
|
||||||
|
#define _CURL_MEMORY_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <curl/curl.h> /* for the typedefs */
|
||||||
|
|
||||||
|
extern curl_malloc_callback Curl_cmalloc;
|
||||||
|
extern curl_free_callback Curl_cfree;
|
||||||
|
extern curl_realloc_callback Curl_crealloc;
|
||||||
|
extern curl_strdup_callback Curl_cstrdup;
|
||||||
|
extern curl_calloc_callback Curl_ccalloc;
|
||||||
|
|
||||||
|
#ifndef CURLDEBUG
|
||||||
|
/* Only do this define-mania if we're not using the memdebug system, as that
|
||||||
|
has preference on this magic. */
|
||||||
|
#undef strdup
|
||||||
|
#define strdup(ptr) Curl_cstrdup(ptr)
|
||||||
|
#undef malloc
|
||||||
|
#define malloc(size) Curl_cmalloc(size)
|
||||||
|
#undef calloc
|
||||||
|
#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
|
||||||
|
#undef realloc
|
||||||
|
#define realloc(ptr,size) Curl_crealloc(ptr, size)
|
||||||
|
#undef free
|
||||||
|
#define free(ptr) Curl_cfree(ptr)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CURL_MEMORY_H */
|
||||||
@@ -44,16 +44,20 @@
|
|||||||
#define SIZEOF_LONG_DOUBLE 0
|
#define SIZEOF_LONG_DOUBLE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIZEOF_SIZE_T
|
||||||
|
/* default to 4 bytes for size_t unless defined in the config.h */
|
||||||
|
#define SIZEOF_SIZE_T 4
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DPRINTF_DEBUG
|
#ifdef DPRINTF_DEBUG
|
||||||
#define HAVE_LONGLONG
|
#define HAVE_LONGLONG
|
||||||
#define LONG_LONG long long
|
#define LONG_LONG long long
|
||||||
#define ENABLE_64BIT
|
#define ENABLE_64BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
|
#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
|
||||||
#define MAX_PARAMETERS 128 /* lame static limit */
|
#define MAX_PARAMETERS 128 /* lame static limit */
|
||||||
@@ -78,7 +82,13 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|||||||
/* Upper-case digits. */
|
/* Upper-case digits. */
|
||||||
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
#define OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1)
|
#define OUTCHAR(x) \
|
||||||
|
do{ \
|
||||||
|
if(stream((unsigned char)(x), (FILE *)data) != -1) \
|
||||||
|
done++; \
|
||||||
|
else \
|
||||||
|
return done; /* return immediately on failure */ \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
/* Data type to read from the arglist */
|
/* Data type to read from the arglist */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -148,6 +158,8 @@ struct asprintf {
|
|||||||
char *buffer; /* allocated buffer */
|
char *buffer; /* allocated buffer */
|
||||||
size_t len; /* length of string */
|
size_t len; /* length of string */
|
||||||
size_t alloc; /* length of alloc */
|
size_t alloc; /* length of alloc */
|
||||||
|
bool fail; /* TRUE if an alloc has failed and thus the output is not
|
||||||
|
the complete data */
|
||||||
};
|
};
|
||||||
|
|
||||||
int curl_msprintf(char *buffer, const char *format, ...);
|
int curl_msprintf(char *buffer, const char *format, ...);
|
||||||
@@ -381,11 +393,12 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos,
|
|||||||
case 'z':
|
case 'z':
|
||||||
/* the code below generates a warning if -Wunreachable-code is
|
/* the code below generates a warning if -Wunreachable-code is
|
||||||
used */
|
used */
|
||||||
if (sizeof(size_t) > sizeof(unsigned long))
|
#if SIZEOF_SIZE_T>4
|
||||||
flags |= FLAGS_LONGLONG;
|
flags |= FLAGS_LONGLONG;
|
||||||
if (sizeof(size_t) > sizeof(unsigned int))
|
#else
|
||||||
flags |= FLAGS_LONG;
|
flags |= FLAGS_LONG;
|
||||||
break;
|
#endif
|
||||||
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
#if SIZEOF_CURL_OFF_T > 4
|
#if SIZEOF_CURL_OFF_T > 4
|
||||||
flags |= FLAGS_LONGLONG;
|
flags |= FLAGS_LONGLONG;
|
||||||
@@ -575,12 +588,12 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int dprintf_formatf(
|
static int dprintf_formatf(
|
||||||
void *data, /* untouched by format(), just sent to the
|
void *data, /* untouched by format(), just sent to the stream() function in
|
||||||
stream() function in the first argument */
|
the second argument */
|
||||||
int (*stream)(int, FILE *), /* function pointer called for each
|
/* function pointer called for each output character */
|
||||||
output character */
|
int (*stream)(int, FILE *),
|
||||||
const char *format, /* %-formatted string */
|
const char *format, /* %-formatted string */
|
||||||
va_list ap_save) /* list of parameters */
|
va_list ap_save) /* list of parameters */
|
||||||
{
|
{
|
||||||
/* Base-36 digits for numbers. */
|
/* Base-36 digits for numbers. */
|
||||||
const char *digits = lower_digits;
|
const char *digits = lower_digits;
|
||||||
@@ -976,13 +989,14 @@ static int dprintf_formatf(
|
|||||||
static int addbyter(int output, FILE *data)
|
static int addbyter(int output, FILE *data)
|
||||||
{
|
{
|
||||||
struct nsprintf *infop=(struct nsprintf *)data;
|
struct nsprintf *infop=(struct nsprintf *)data;
|
||||||
|
unsigned char outc = (unsigned char)output;
|
||||||
|
|
||||||
if(infop->length < infop->max) {
|
if(infop->length < infop->max) {
|
||||||
/* only do this if we haven't reached max length yet */
|
/* only do this if we haven't reached max length yet */
|
||||||
infop->buffer[0] = (char)output; /* store */
|
infop->buffer[0] = outc; /* store */
|
||||||
infop->buffer++; /* increase pointer */
|
infop->buffer++; /* increase pointer */
|
||||||
infop->length++; /* we are now one byte larger */
|
infop->length++; /* we are now one byte larger */
|
||||||
return output; /* fputc() returns like this on success */
|
return outc; /* fputc() returns like this on success */
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1023,11 +1037,14 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
|
|||||||
static int alloc_addbyter(int output, FILE *data)
|
static int alloc_addbyter(int output, FILE *data)
|
||||||
{
|
{
|
||||||
struct asprintf *infop=(struct asprintf *)data;
|
struct asprintf *infop=(struct asprintf *)data;
|
||||||
|
unsigned char outc = (unsigned char)output;
|
||||||
|
|
||||||
if(!infop->buffer) {
|
if(!infop->buffer) {
|
||||||
infop->buffer=(char *)malloc(32);
|
infop->buffer=(char *)malloc(32);
|
||||||
if(!infop->buffer)
|
if(!infop->buffer) {
|
||||||
|
infop->fail = TRUE;
|
||||||
return -1; /* fail */
|
return -1; /* fail */
|
||||||
|
}
|
||||||
infop->alloc = 32;
|
infop->alloc = 32;
|
||||||
infop->len =0;
|
infop->len =0;
|
||||||
}
|
}
|
||||||
@@ -1037,17 +1054,18 @@ static int alloc_addbyter(int output, FILE *data)
|
|||||||
newptr = (char *)realloc(infop->buffer, infop->alloc*2);
|
newptr = (char *)realloc(infop->buffer, infop->alloc*2);
|
||||||
|
|
||||||
if(!newptr) {
|
if(!newptr) {
|
||||||
|
infop->fail = TRUE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
infop->buffer = newptr;
|
infop->buffer = newptr;
|
||||||
infop->alloc *= 2;
|
infop->alloc *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
infop->buffer[ infop->len ] = (char)output;
|
infop->buffer[ infop->len ] = outc;
|
||||||
|
|
||||||
infop->len++;
|
infop->len++;
|
||||||
|
|
||||||
return output; /* fputc() returns like this on success */
|
return outc; /* fputc() returns like this on success */
|
||||||
}
|
}
|
||||||
|
|
||||||
char *curl_maprintf(const char *format, ...)
|
char *curl_maprintf(const char *format, ...)
|
||||||
@@ -1059,11 +1077,12 @@ char *curl_maprintf(const char *format, ...)
|
|||||||
info.buffer = NULL;
|
info.buffer = NULL;
|
||||||
info.len = 0;
|
info.len = 0;
|
||||||
info.alloc = 0;
|
info.alloc = 0;
|
||||||
|
info.fail = FALSE;
|
||||||
|
|
||||||
va_start(ap_save, format);
|
va_start(ap_save, format);
|
||||||
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
|
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
|
||||||
va_end(ap_save);
|
va_end(ap_save);
|
||||||
if(-1 == retcode) {
|
if((-1 == retcode) || info.fail) {
|
||||||
if(info.alloc)
|
if(info.alloc)
|
||||||
free(info.buffer);
|
free(info.buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1084,9 +1103,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
|
|||||||
info.buffer = NULL;
|
info.buffer = NULL;
|
||||||
info.len = 0;
|
info.len = 0;
|
||||||
info.alloc = 0;
|
info.alloc = 0;
|
||||||
|
info.fail = FALSE;
|
||||||
|
|
||||||
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
|
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
|
||||||
if(-1 == retcode) {
|
if((-1 == retcode) || info.fail) {
|
||||||
if(info.alloc)
|
if(info.alloc)
|
||||||
free(info.buffer);
|
free(info.buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1103,9 +1123,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
|
|||||||
static int storebuffer(int output, FILE *data)
|
static int storebuffer(int output, FILE *data)
|
||||||
{
|
{
|
||||||
char **buffer = (char **)data;
|
char **buffer = (char **)data;
|
||||||
**buffer = (char)output;
|
unsigned char outc = (unsigned char)output;
|
||||||
|
**buffer = outc;
|
||||||
(*buffer)++;
|
(*buffer)++;
|
||||||
return output; /* act like fputc() ! */
|
return outc; /* act like fputc() ! */
|
||||||
}
|
}
|
||||||
|
|
||||||
int curl_msprintf(char *buffer, const char *format, ...)
|
int curl_msprintf(char *buffer, const char *format, ...)
|
||||||
|
|||||||
7
lib/msvcproj.foot
Normal file
7
lib/msvcproj.foot
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
92
lib/msvcproj.head
Normal file
92
lib/msvcproj.head
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=curllib - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "curllib.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "curllib - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "." /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /D "_WINDLL" /FR /FD /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /FR /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /WX /YX
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib ws2_32.lib winmm.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
||||||
|
# SUBTRACT LINK32 /nodefaultlib
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "curllib - Win32 Release"
|
||||||
|
# Name "curllib - Win32 Debug"
|
||||||
85
lib/multi.c
85
lib/multi.c
@@ -1,8 +1,8 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
* / __| | | | |_) | |
|
* / __| | | | |_) | |
|
||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
*
|
*
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
* 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
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
* furnished to do so, under the terms of the COPYING file.
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
@@ -42,11 +42,10 @@
|
|||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Curl_message {
|
struct Curl_message {
|
||||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||||
@@ -72,7 +71,7 @@ struct Curl_one_easy {
|
|||||||
/* first, two fields for the linked list of these */
|
/* first, two fields for the linked list of these */
|
||||||
struct Curl_one_easy *next;
|
struct Curl_one_easy *next;
|
||||||
struct Curl_one_easy *prev;
|
struct Curl_one_easy *prev;
|
||||||
|
|
||||||
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
struct SessionHandle *easy_handle; /* the easy handle for this unit */
|
||||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ struct Curl_multi {
|
|||||||
long type;
|
long type;
|
||||||
|
|
||||||
/* We have a linked list with easy handles */
|
/* We have a linked list with easy handles */
|
||||||
struct Curl_one_easy easy;
|
struct Curl_one_easy easy;
|
||||||
/* This is the amount of entries in the linked list above. */
|
/* This is the amount of entries in the linked list above. */
|
||||||
int num_easy;
|
int num_easy;
|
||||||
|
|
||||||
@@ -121,6 +120,8 @@ CURLM *curl_multi_init(void)
|
|||||||
memset(multi, 0, sizeof(struct Curl_multi));
|
memset(multi, 0, sizeof(struct Curl_multi));
|
||||||
multi->type = CURL_MULTI_HANDLE;
|
multi->type = CURL_MULTI_HANDLE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
multi->hostcache = Curl_mk_dnscache();
|
multi->hostcache = Curl_mk_dnscache();
|
||||||
if(!multi->hostcache) {
|
if(!multi->hostcache) {
|
||||||
@@ -140,7 +141,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
|||||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
/* Verify that we got a somewhat good easy handle too */
|
/* Verify that we got a somewhat good easy handle too */
|
||||||
if(!GOOD_EASY_HANDLE(easy_handle))
|
if(!GOOD_EASY_HANDLE(easy_handle))
|
||||||
return CURLM_BAD_EASY_HANDLE;
|
return CURLM_BAD_EASY_HANDLE;
|
||||||
@@ -149,7 +150,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
|||||||
easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy));
|
easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy));
|
||||||
if(!easy)
|
if(!easy)
|
||||||
return CURLM_OUT_OF_MEMORY;
|
return CURLM_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* clean it all first (just to be sure) */
|
/* clean it all first (just to be sure) */
|
||||||
memset(easy, 0, sizeof(struct Curl_one_easy));
|
memset(easy, 0, sizeof(struct Curl_one_easy));
|
||||||
|
|
||||||
@@ -159,11 +160,11 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
|||||||
|
|
||||||
/* for multi interface connections, we share DNS cache automaticly */
|
/* for multi interface connections, we share DNS cache automaticly */
|
||||||
easy->easy_handle->hostcache = multi->hostcache;
|
easy->easy_handle->hostcache = multi->hostcache;
|
||||||
|
|
||||||
/* We add this new entry first in the list. We make our 'next' point to the
|
/* 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 */
|
previous next and our 'prev' point back to the 'first' struct */
|
||||||
easy->next = multi->easy.next;
|
easy->next = multi->easy.next;
|
||||||
easy->prev = &multi->easy;
|
easy->prev = &multi->easy;
|
||||||
|
|
||||||
/* make 'easy' the first node in the chain */
|
/* make 'easy' the first node in the chain */
|
||||||
multi->easy.next = easy;
|
multi->easy.next = easy;
|
||||||
@@ -188,7 +189,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
|||||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
/* Verify that we got a somewhat good easy handle too */
|
/* Verify that we got a somewhat good easy handle too */
|
||||||
if(!GOOD_EASY_HANDLE(curl_handle))
|
if(!GOOD_EASY_HANDLE(curl_handle))
|
||||||
return CURLM_BAD_EASY_HANDLE;
|
return CURLM_BAD_EASY_HANDLE;
|
||||||
@@ -206,14 +207,14 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
|||||||
|
|
||||||
/* clear out the usage of the shared DNS cache */
|
/* clear out the usage of the shared DNS cache */
|
||||||
easy->easy_handle->hostcache = NULL;
|
easy->easy_handle->hostcache = NULL;
|
||||||
|
|
||||||
/* make the previous node point to our next */
|
/* make the previous node point to our next */
|
||||||
if(easy->prev)
|
if(easy->prev)
|
||||||
easy->prev->next = easy->next;
|
easy->prev->next = easy->next;
|
||||||
/* make our next point to our previous node */
|
/* make our next point to our previous node */
|
||||||
if(easy->next)
|
if(easy->next)
|
||||||
easy->next->prev = easy->prev;
|
easy->next->prev = easy->prev;
|
||||||
|
|
||||||
/* NOTE NOTE NOTE
|
/* NOTE NOTE NOTE
|
||||||
We do not touch the easy handle here! */
|
We do not touch the easy handle here! */
|
||||||
if (easy->msg)
|
if (easy->msg)
|
||||||
@@ -251,8 +252,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
|||||||
break;
|
break;
|
||||||
case CURLM_STATE_WAITRESOLVE:
|
case CURLM_STATE_WAITRESOLVE:
|
||||||
/* waiting for a resolve to complete */
|
/* waiting for a resolve to complete */
|
||||||
Curl_multi_ares_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
Curl_fdset(easy->easy_conn, read_fd_set, write_fd_set, &this_max_fd);
|
||||||
&this_max_fd);
|
|
||||||
if(this_max_fd > *max_fd)
|
if(this_max_fd > *max_fd)
|
||||||
*max_fd = this_max_fd;
|
*max_fd = this_max_fd;
|
||||||
break;
|
break;
|
||||||
@@ -273,7 +273,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
|||||||
/* When in DO_MORE state, we could be either waiting for us
|
/* When in DO_MORE state, we could be either waiting for us
|
||||||
to connect to a remote site, or we could wait for that site
|
to connect to a remote site, or we could wait for that site
|
||||||
to connect to us. It makes a difference in the way: if we
|
to connect to us. It makes a difference in the way: if we
|
||||||
connect to the site we wait for the socket to become writable, if
|
connect to the site we wait for the socket to become writable, if
|
||||||
the site connects to us we wait for it to become readable */
|
the site connects to us we wait for it to become readable */
|
||||||
sockfd = conn->sock[SECONDARYSOCKET];
|
sockfd = conn->sock[SECONDARYSOCKET];
|
||||||
FD_SET(sockfd, write_fd_set);
|
FD_SET(sockfd, write_fd_set);
|
||||||
@@ -331,18 +331,25 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
char *gotourl;
|
char *gotourl;
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(easy->easy_handle);
|
||||||
|
|
||||||
easy->result = Curl_done(easy->easy_conn);
|
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
gotourl = strdup(easy->easy_handle->change.url);
|
gotourl = strdup(easy->easy_handle->change.url);
|
||||||
easy->easy_handle->change.url_changed = FALSE;
|
if(gotourl) {
|
||||||
easy->result = Curl_follow(easy->easy_handle, gotourl);
|
easy->easy_handle->change.url_changed = FALSE;
|
||||||
if(CURLE_OK == easy->result)
|
easy->result = Curl_follow(easy->easy_handle, gotourl);
|
||||||
easy->state = CURLM_STATE_CONNECT;
|
if(CURLE_OK == easy->result)
|
||||||
else
|
easy->state = CURLM_STATE_CONNECT;
|
||||||
free(gotourl);
|
else
|
||||||
|
free(gotourl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
easy->result = CURLE_OUT_OF_MEMORY;
|
||||||
|
easy->state = CURLM_STATE_COMPLETED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
easy->easy_handle->change.url_changed = FALSE;
|
easy->easy_handle->change.url_changed = FALSE;
|
||||||
|
|
||||||
switch(easy->state) {
|
switch(easy->state) {
|
||||||
@@ -353,8 +360,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
/* after init, go CONNECT */
|
/* after init, go CONNECT */
|
||||||
easy->state = CURLM_STATE_CONNECT;
|
easy->state = CURLM_STATE_CONNECT;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
|
||||||
easy->easy_handle->state.used_interface = Curl_if_multi;
|
easy->easy_handle->state.used_interface = Curl_if_multi;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -397,7 +404,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
|
|
||||||
easy->state = CURLM_STATE_WAITCONNECT;
|
easy->state = CURLM_STATE_WAITCONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CURLE_OK != easy->result) {
|
if(CURLE_OK != easy->result) {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
Curl_disconnect(easy->easy_conn); /* disconnect properly */
|
Curl_disconnect(easy->easy_conn); /* disconnect properly */
|
||||||
@@ -413,7 +420,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
easy->easy_conn->sock[FIRSTSOCKET],
|
easy->easy_conn->sock[FIRSTSOCKET],
|
||||||
&connected);
|
&connected);
|
||||||
if(connected)
|
if(connected)
|
||||||
easy->result = Curl_protocol_connect(easy->easy_conn, NULL);
|
easy->result = Curl_protocol_connect(easy->easy_conn);
|
||||||
|
|
||||||
if(CURLE_OK != easy->result) {
|
if(CURLE_OK != easy->result) {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
@@ -425,7 +432,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
if(connected) {
|
if(connected) {
|
||||||
/* after the connect has completed, go DO */
|
/* after the connect has completed, go DO */
|
||||||
easy->state = CURLM_STATE_DO;
|
easy->state = CURLM_STATE_DO;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -446,7 +453,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
easy->result = Curl_readwrite_init(easy->easy_conn);
|
easy->result = Curl_readwrite_init(easy->easy_conn);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
easy->state = CURLM_STATE_PERFORM;
|
easy->state = CURLM_STATE_PERFORM;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,7 +478,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
|
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
easy->state = CURLM_STATE_PERFORM;
|
easy->state = CURLM_STATE_PERFORM;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -493,7 +500,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
easy->easy_conn->sock[SECONDARYSOCKET]=-1;
|
easy->easy_conn->sock[SECONDARYSOCKET]=-1;
|
||||||
}
|
}
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(easy->easy_handle);
|
||||||
Curl_done(easy->easy_conn);
|
Curl_done(&easy->easy_conn, easy->result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after the transfer is done, go DONE */
|
/* after the transfer is done, go DONE */
|
||||||
@@ -506,7 +513,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
if(easy->easy_conn->newurl) {
|
if(easy->easy_conn->newurl) {
|
||||||
char *newurl = easy->easy_conn->newurl;
|
char *newurl = easy->easy_conn->newurl;
|
||||||
easy->easy_conn->newurl = NULL;
|
easy->easy_conn->newurl = NULL;
|
||||||
easy->result = Curl_done(easy->easy_conn);
|
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||||
if(easy->result == CURLE_OK)
|
if(easy->result == CURLE_OK)
|
||||||
easy->result = Curl_follow(easy->easy_handle, newurl);
|
easy->result = Curl_follow(easy->easy_handle, newurl);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
@@ -516,13 +523,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
easy->state = CURLM_STATE_DONE;
|
easy->state = CURLM_STATE_DONE;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CURLM_STATE_DONE:
|
case CURLM_STATE_DONE:
|
||||||
/* post-transfer command */
|
/* post-transfer command */
|
||||||
easy->result = Curl_done(easy->easy_conn);
|
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
|
||||||
|
|
||||||
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
||||||
it doesn't matter what the Curl_done() returned! */
|
it doesn't matter what the Curl_done() returned! */
|
||||||
@@ -619,7 +626,7 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
|
|||||||
|
|
||||||
if(GOOD_MULTI_HANDLE(multi)) {
|
if(GOOD_MULTI_HANDLE(multi)) {
|
||||||
struct Curl_one_easy *easy;
|
struct Curl_one_easy *easy;
|
||||||
|
|
||||||
if(!multi->num_msgs)
|
if(!multi->num_msgs)
|
||||||
return NULL; /* no messages left to return */
|
return NULL; /* no messages left to return */
|
||||||
|
|
||||||
|
|||||||
@@ -45,14 +45,13 @@
|
|||||||
|
|
||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
#include "strtok.h"
|
#include "strtok.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#ifdef CURLDEBUG
|
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Debug this single source file with:
|
/* Debug this single source file with:
|
||||||
'make netrc' then run './netrc'!
|
'make netrc' then run './netrc'!
|
||||||
|
|||||||
322
lib/nwlib.c
322
lib/nwlib.c
@@ -30,21 +30,23 @@
|
|||||||
#include <nks/thread.h>
|
#include <nks/thread.h>
|
||||||
#include <nks/synch.h>
|
#include <nks/synch.h>
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int _errno;
|
int _errno;
|
||||||
void *twentybytes;
|
void *twentybytes;
|
||||||
} libthreaddata_t;
|
} libthreaddata_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int z;
|
int z;
|
||||||
void *tenbytes;
|
void *tenbytes;
|
||||||
NXKey_t perthreadkey; /* if -1, no key obtained... */
|
NXKey_t perthreadkey; /* if -1, no key obtained... */
|
||||||
NXMutex_t *lock;
|
NXMutex_t *lock;
|
||||||
} libdata_t;
|
} libdata_t;
|
||||||
|
|
||||||
int gLibId = -1;
|
int gLibId = -1;
|
||||||
@@ -58,24 +60,24 @@ void DisposeThreadData ( void * );
|
|||||||
int GetOrSetUpData ( int id, libdata_t **data, libthreaddata_t **threaddata );
|
int GetOrSetUpData ( int id, libdata_t **data, libthreaddata_t **threaddata );
|
||||||
|
|
||||||
|
|
||||||
int _NonAppStart
|
int _NonAppStart( void *NLMHandle,
|
||||||
(
|
void *errorScreen,
|
||||||
void *NLMHandle,
|
const char *cmdLine,
|
||||||
void *errorScreen,
|
const char *loadDirPath,
|
||||||
const char *cmdLine,
|
size_t uninitializedDataLength,
|
||||||
const char *loadDirPath,
|
void *NLMFileHandle,
|
||||||
size_t uninitializedDataLength,
|
int (*readRoutineP)( int conn,
|
||||||
void *NLMFileHandle,
|
void *fileHandle, size_t offset,
|
||||||
int (*readRoutineP)( int conn, void *fileHandle, size_t offset,
|
size_t nbytes,
|
||||||
size_t nbytes, size_t *bytesRead, void *buffer ),
|
size_t *bytesRead,
|
||||||
size_t customDataOffset,
|
void *buffer ),
|
||||||
size_t customDataSize,
|
size_t customDataOffset,
|
||||||
int messageCount,
|
size_t customDataSize,
|
||||||
const char **messages
|
int messageCount,
|
||||||
)
|
const char **messages )
|
||||||
{
|
{
|
||||||
NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
|
NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#pragma unused(cmdLine)
|
#pragma unused(cmdLine)
|
||||||
#pragma unused(loadDirPath)
|
#pragma unused(loadDirPath)
|
||||||
@@ -94,35 +96,33 @@ int _NonAppStart
|
|||||||
** to accept calls into us. If we succeed, we return non-zero and the NetWare
|
** to accept calls into us. If we succeed, we return non-zero and the NetWare
|
||||||
** Loader will leave us up, otherwise we fail to load and get dumped.
|
** Loader will leave us up, otherwise we fail to load and get dumped.
|
||||||
*/
|
*/
|
||||||
gAllocTag = AllocateResourceTag(NLMHandle,
|
gAllocTag = AllocateResourceTag(NLMHandle,
|
||||||
"<library-name> memory allocations", AllocSignature);
|
"<library-name> memory allocations",
|
||||||
|
AllocSignature);
|
||||||
|
|
||||||
if (!gAllocTag)
|
if (!gAllocTag) {
|
||||||
{
|
OutputToScreen(errorScreen, "Unable to allocate resource tag for "
|
||||||
OutputToScreen(errorScreen, "Unable to allocate resource tag for "
|
"library memory allocations.\n");
|
||||||
"library memory allocations.\n");
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gLibId = register_library(DisposeLibraryData);
|
gLibId = register_library(DisposeLibraryData);
|
||||||
|
|
||||||
if (gLibId < -1)
|
if (gLibId < -1) {
|
||||||
{
|
OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
|
||||||
OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gLibHandle = NLMHandle;
|
gLibHandle = NLMHandle;
|
||||||
|
|
||||||
gLibLock = NXMutexAlloc(0, 0, &liblock);
|
gLibLock = NXMutexAlloc(0, 0, &liblock);
|
||||||
|
|
||||||
|
if (!gLibLock) {
|
||||||
|
OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gLibLock)
|
return 0;
|
||||||
{
|
|
||||||
OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -131,8 +131,8 @@ int _NonAppStart
|
|||||||
*/
|
*/
|
||||||
void _NonAppStop( void )
|
void _NonAppStop( void )
|
||||||
{
|
{
|
||||||
(void) unregister_library(gLibId);
|
(void) unregister_library(gLibId);
|
||||||
NXMutexFree(gLibLock);
|
NXMutexFree(gLibLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -151,31 +151,26 @@ int _NonAppCheckUnload( void )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetOrSetUpData
|
int GetOrSetUpData(int id, libdata_t **appData,
|
||||||
(
|
libthreaddata_t **threadData )
|
||||||
int id,
|
|
||||||
libdata_t **appData,
|
|
||||||
libthreaddata_t **threadData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
libdata_t *app_data;
|
libdata_t *app_data;
|
||||||
libthreaddata_t *thread_data;
|
libthreaddata_t *thread_data;
|
||||||
NXKey_t key;
|
NXKey_t key;
|
||||||
NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
|
NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
thread_data = (libthreaddata_t *) NULL;
|
thread_data = (libthreaddata_t *) NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Attempt to get our data for the application calling us. This is where we
|
** Attempt to get our data for the application calling us. This is where we
|
||||||
** store whatever application-specific information we need to carry in support
|
** store whatever application-specific information we need to carry in support
|
||||||
** of calling applications.
|
** of calling applications.
|
||||||
*/
|
*/
|
||||||
app_data = (libdata_t *) get_app_data(id);
|
app_data = (libdata_t *) get_app_data(id);
|
||||||
|
|
||||||
if (!app_data)
|
if (!app_data) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
** This application hasn't called us before; set up application AND per-thread
|
** This application hasn't called us before; set up application AND per-thread
|
||||||
** data. Of course, just in case a thread from this same application is calling
|
** data. Of course, just in case a thread from this same application is calling
|
||||||
@@ -184,31 +179,27 @@ int GetOrSetUpData
|
|||||||
** that other thread that was too late to create the data and the first thread
|
** that other thread that was too late to create the data and the first thread
|
||||||
** in will have created it.
|
** in will have created it.
|
||||||
*/
|
*/
|
||||||
NXLock(gLibLock);
|
NXLock(gLibLock);
|
||||||
|
|
||||||
if (!(app_data = (libdata_t *) get_app_data(id)))
|
if (!(app_data = (libdata_t *) get_app_data(id))) {
|
||||||
{
|
app_data = (libdata_t *) malloc(sizeof(libdata_t));
|
||||||
app_data = (libdata_t *) malloc(sizeof(libdata_t));
|
|
||||||
|
|
||||||
if (app_data)
|
if (app_data) {
|
||||||
{
|
memset(app_data, 0, sizeof(libdata_t));
|
||||||
memset(app_data, 0, sizeof(libdata_t));
|
|
||||||
|
app_data->tenbytes = malloc(10);
|
||||||
app_data->tenbytes = malloc(10);
|
app_data->lock = NXMutexAlloc(0, 0, &liblock);
|
||||||
app_data->lock = NXMutexAlloc(0, 0, &liblock);
|
|
||||||
|
if (!app_data->tenbytes || !app_data->lock) {
|
||||||
if (!app_data->tenbytes || !app_data->lock)
|
if (app_data->lock)
|
||||||
{
|
NXMutexFree(app_data->lock);
|
||||||
if (app_data->lock)
|
|
||||||
NXMutexFree(app_data->lock);
|
free(app_data);
|
||||||
|
app_data = (libdata_t *) NULL;
|
||||||
free(app_data);
|
err = ENOMEM;
|
||||||
app_data = (libdata_t *) NULL;
|
}
|
||||||
err = ENOMEM;
|
|
||||||
}
|
if (app_data) {
|
||||||
|
|
||||||
if (app_data)
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
** Here we burn in the application data that we were trying to get by calling
|
** Here we burn in the application data that we were trying to get by calling
|
||||||
** get_app_data(). Next time we call the first function, we'll get this data
|
** get_app_data(). Next time we call the first function, we'll get this data
|
||||||
@@ -216,39 +207,35 @@ int GetOrSetUpData
|
|||||||
** for the calling thread, something we'll have to do on each application
|
** for the calling thread, something we'll have to do on each application
|
||||||
** thread the first time it calls us.
|
** thread the first time it calls us.
|
||||||
*/
|
*/
|
||||||
err = set_app_data(gLibId, app_data);
|
err = set_app_data(gLibId, app_data);
|
||||||
|
|
||||||
if (err)
|
if (err) {
|
||||||
{
|
free(app_data);
|
||||||
free(app_data);
|
app_data = (libdata_t *) NULL;
|
||||||
app_data = (libdata_t *) NULL;
|
err = ENOMEM;
|
||||||
err = ENOMEM;
|
}
|
||||||
}
|
else {
|
||||||
else
|
/* create key for thread-specific data... */
|
||||||
{
|
err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
|
||||||
/* create key for thread-specific data... */
|
|
||||||
err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
|
if (err) /* (no more keys left?) */
|
||||||
|
key = -1;
|
||||||
if (err) /* (no more keys left?) */
|
|
||||||
key = -1;
|
app_data->perthreadkey = key;
|
||||||
|
}
|
||||||
app_data->perthreadkey = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
NXUnlock(gLibLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NXUnlock(gLibLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (app_data)
|
if (app_data) {
|
||||||
{
|
key = app_data->perthreadkey;
|
||||||
key = app_data->perthreadkey;
|
|
||||||
|
if (key != -1 /* couldn't create a key? no thread data */
|
||||||
if ( key != -1 /* couldn't create a key? no thread data */
|
&& !(err = NXKeyGetValue(key, (void **) &thread_data))
|
||||||
&& !(err = NXKeyGetValue(key, (void **) &thread_data))
|
&& !thread_data) {
|
||||||
&& !thread_data)
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
** Allocate the per-thread data for the calling thread. Regardless of whether
|
** Allocate the per-thread data for the calling thread. Regardless of whether
|
||||||
** there was already application data or not, this may be the first call by a
|
** there was already application data or not, this may be the first call by a
|
||||||
@@ -256,71 +243,58 @@ int GetOrSetUpData
|
|||||||
** important, this just helps to demonstrate that we can have arbitrarily
|
** important, this just helps to demonstrate that we can have arbitrarily
|
||||||
** complex per-thread data.
|
** complex per-thread data.
|
||||||
*/
|
*/
|
||||||
thread_data = (libthreaddata_t *) malloc(sizeof(libthreaddata_t));
|
thread_data = (libthreaddata_t *) malloc(sizeof(libthreaddata_t));
|
||||||
|
|
||||||
if (thread_data)
|
if (thread_data) {
|
||||||
{
|
thread_data->_errno = 0;
|
||||||
thread_data->_errno = 0;
|
thread_data->twentybytes = malloc(20);
|
||||||
thread_data->twentybytes = malloc(20);
|
|
||||||
|
if (!thread_data->twentybytes) {
|
||||||
if (!thread_data->twentybytes)
|
free(thread_data);
|
||||||
{
|
thread_data = (libthreaddata_t *) NULL;
|
||||||
free(thread_data);
|
err = ENOMEM;
|
||||||
thread_data = (libthreaddata_t *) NULL;
|
|
||||||
err = ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = NXKeySetValue(key, thread_data)))
|
|
||||||
{
|
|
||||||
free(thread_data->twentybytes);
|
|
||||||
free(thread_data);
|
|
||||||
thread_data = (libthreaddata_t *) NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = NXKeySetValue(key, thread_data))) {
|
||||||
|
free(thread_data->twentybytes);
|
||||||
|
free(thread_data);
|
||||||
|
thread_data = (libthreaddata_t *) NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (appData)
|
if (appData)
|
||||||
*appData = app_data;
|
*appData = app_data;
|
||||||
|
|
||||||
if (threadData)
|
if (threadData)
|
||||||
*threadData = thread_data;
|
*threadData = thread_data;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DisposeLibraryData
|
int DisposeLibraryData( void *data)
|
||||||
(
|
|
||||||
void *data
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (data)
|
if (data) {
|
||||||
{
|
void *tenbytes = ((libdata_t *) data)->tenbytes;
|
||||||
void *tenbytes = ((libdata_t *) data)->tenbytes;
|
|
||||||
|
if (tenbytes)
|
||||||
|
free(tenbytes);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (tenbytes)
|
return 0;
|
||||||
free(tenbytes);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisposeThreadData
|
void DisposeThreadData(void *data)
|
||||||
(
|
|
||||||
void *data
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (data)
|
if (data) {
|
||||||
{
|
void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
|
||||||
void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
|
|
||||||
|
if (twentybytes)
|
||||||
if (twentybytes)
|
free(twentybytes);
|
||||||
free(twentybytes);
|
|
||||||
|
free(data);
|
||||||
free(data);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user