Compare commits
163 Commits
curl-7_9
...
curl-7_9_1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
329bcf3a71 | ||
![]() |
0cb12d7e78 | ||
![]() |
3bfa06c9a2 | ||
![]() |
f34573c8e2 | ||
![]() |
4163b86cd2 | ||
![]() |
5b948512f9 | ||
![]() |
2297a7a70c | ||
![]() |
dc82f9e6df | ||
![]() |
e60e7414b9 | ||
![]() |
c6caa9fd60 | ||
![]() |
c84ad40ccd | ||
![]() |
ab7f25ab41 | ||
![]() |
6d213e207d | ||
![]() |
9b6545c479 | ||
![]() |
96fb118251 | ||
![]() |
617d6eb7ce | ||
![]() |
99888388dc | ||
![]() |
7d24ce9651 | ||
![]() |
cbc35b1fb8 | ||
![]() |
027fc719cc | ||
![]() |
f6b2e9e8a4 | ||
![]() |
c4f1a9f690 | ||
![]() |
542055074b | ||
![]() |
7b93348aae | ||
![]() |
eaf475b538 | ||
![]() |
4118c68df1 | ||
![]() |
69d5d88259 | ||
![]() |
7e6a36ea7b | ||
![]() |
6878c0b88f | ||
![]() |
bbdc9f15e7 | ||
![]() |
ae4f8243a9 | ||
![]() |
1c83dee948 | ||
![]() |
b66dedc017 | ||
![]() |
b07e2a08f9 | ||
![]() |
64543e09ec | ||
![]() |
58936efff6 | ||
![]() |
dbd32278f8 | ||
![]() |
6d35984286 | ||
![]() |
c046dc904c | ||
![]() |
bc8375a1e8 | ||
![]() |
83877d5ec6 | ||
![]() |
3f248dd163 | ||
![]() |
c9954d1941 | ||
![]() |
e165332211 | ||
![]() |
d25310cb6f | ||
![]() |
fbb9d23a25 | ||
![]() |
2d32e8831b | ||
![]() |
42a9d96fae | ||
![]() |
3edd9b4dfc | ||
![]() |
1a8cf79ae0 | ||
![]() |
b736bdc8e5 | ||
![]() |
babb985f1a | ||
![]() |
b22a5f756c | ||
![]() |
d733061873 | ||
![]() |
bca0c8d253 | ||
![]() |
53ac8004e7 | ||
![]() |
7b76499e82 | ||
![]() |
9f45190fa1 | ||
![]() |
f933cb3b75 | ||
![]() |
c6822f5a7f | ||
![]() |
4e276b1b68 | ||
![]() |
50e9f8ffd3 | ||
![]() |
7d3daa598f | ||
![]() |
7349940bdb | ||
![]() |
78000dbd5d | ||
![]() |
b585f411cd | ||
![]() |
5ccd6bb842 | ||
![]() |
5193894603 | ||
![]() |
29b76a52fb | ||
![]() |
0436bc22f2 | ||
![]() |
cd16efa2f2 | ||
![]() |
56562bad59 | ||
![]() |
a26081b555 | ||
![]() |
aa9c01ad3e | ||
![]() |
4e37187e44 | ||
![]() |
74d5a6fb3b | ||
![]() |
83da58ce91 | ||
![]() |
45cc78fdbc | ||
![]() |
010044e03c | ||
![]() |
db0e3cc60c | ||
![]() |
8dd6a4e369 | ||
![]() |
92abbcef4c | ||
![]() |
1e8f0c5771 | ||
![]() |
532bca41e5 | ||
![]() |
b438c46764 | ||
![]() |
ef48c73783 | ||
![]() |
2c5e416591 | ||
![]() |
8e91d5de8e | ||
![]() |
2f85f3b147 | ||
![]() |
20a47acb3a | ||
![]() |
6bc85a94f9 | ||
![]() |
71bf8a6985 | ||
![]() |
59a76e4010 | ||
![]() |
65b9c0d44d | ||
![]() |
f2a25966cf | ||
![]() |
51afc3d8c5 | ||
![]() |
0c2f60036a | ||
![]() |
3dcdcfc572 | ||
![]() |
9f8c51cbd8 | ||
![]() |
de79348a90 | ||
![]() |
56bc31e9f9 | ||
![]() |
a9181f8f00 | ||
![]() |
3685f792cb | ||
![]() |
e227a276ce | ||
![]() |
7b5b60d275 | ||
![]() |
e719f4169c | ||
![]() |
d8fb2b2e63 | ||
![]() |
fdeaae678d | ||
![]() |
f30102f038 | ||
![]() |
a27ac6f394 | ||
![]() |
093c0a098e | ||
![]() |
c3363f833c | ||
![]() |
47def8091c | ||
![]() |
cfb32ec0cd | ||
![]() |
5d9ae88f58 | ||
![]() |
9d066935e5 | ||
![]() |
bc40063e07 | ||
![]() |
3c92d45386 | ||
![]() |
fcf4fccfa4 | ||
![]() |
eafd2c6bd5 | ||
![]() |
64f00454e5 | ||
![]() |
d678727430 | ||
![]() |
efc15fb128 | ||
![]() |
3d4cd8c9aa | ||
![]() |
420259993e | ||
![]() |
66087bdac6 | ||
![]() |
ac70a43452 | ||
![]() |
72dbe9da72 | ||
![]() |
dd02881788 | ||
![]() |
ced8955325 | ||
![]() |
51ca5fcbe0 | ||
![]() |
56ff2aa059 | ||
![]() |
9f77771ff9 | ||
![]() |
f0fa858885 | ||
![]() |
3298630500 | ||
![]() |
dc27488c47 | ||
![]() |
375e615a6d | ||
![]() |
6918427fae | ||
![]() |
9d342bbf07 | ||
![]() |
afc81ada0c | ||
![]() |
5cd267b2be | ||
![]() |
09da90076f | ||
![]() |
d0079d9054 | ||
![]() |
ede5b54edc | ||
![]() |
c5fdeef41d | ||
![]() |
6ca45beaed | ||
![]() |
2a07626aa8 | ||
![]() |
9127554852 | ||
![]() |
9ff28a8237 | ||
![]() |
e9aa07f660 | ||
![]() |
88e21894c7 | ||
![]() |
09da2c1767 | ||
![]() |
ae2ecfc5cb | ||
![]() |
cc610f0d1f | ||
![]() |
8333644c84 | ||
![]() |
4d13b2cc64 | ||
![]() |
48dc74aecc | ||
![]() |
888d39e083 | ||
![]() |
7239ecd456 | ||
![]() |
598e8dfbfb | ||
![]() |
9efdb68035 | ||
![]() |
14b898cb05 | ||
![]() |
8d16b2b119 |
257
CHANGES
257
CHANGES
@@ -6,6 +6,263 @@
|
|||||||
|
|
||||||
History of Changes
|
History of Changes
|
||||||
|
|
||||||
|
Version 7.9.1
|
||||||
|
|
||||||
|
Daniel (4 November 2001)
|
||||||
|
- I've added a number of new test cases the last few days. A few of them since
|
||||||
|
I got reports that hinted on problems on timeouts, so I added four tests
|
||||||
|
with timeouts for all sorts of protocols and stuff. I also came to think of
|
||||||
|
a few other error scenarios that we currently didn't test properly, so I
|
||||||
|
wrote up tests for a few of those too.
|
||||||
|
|
||||||
|
Daniel (2 November 2001)
|
||||||
|
- Replaced read() and write() with recv() and send() for socket operations
|
||||||
|
even under normal unixes.
|
||||||
|
|
||||||
|
Daniel (1 November 2001)
|
||||||
|
- When an FTP transfer was aborted due to a timeout, it wasn't really aware of
|
||||||
|
how many bytes that had been transferred and the error text always said 0
|
||||||
|
bytes. I modified this to output the actually transferred amount! :-)
|
||||||
|
|
||||||
|
- The FTP fixes in pre7 didn't compile on IPv6 enabled hosts. Does now. I also
|
||||||
|
added more comments in the lib/ftp.c source file.
|
||||||
|
|
||||||
|
- Minor updates to the FAQ, added a brand new section to the web site about
|
||||||
|
the name issue (who owns "curl"? will someone sue us? etc etc):
|
||||||
|
http://curl.haxx.se/legal/thename.html
|
||||||
|
|
||||||
|
Version 7.9.1-pre7
|
||||||
|
|
||||||
|
Daniel (31 October 2001)
|
||||||
|
- The curl_easy_getinfo() timers accidentally lost they're subsecond accuracy
|
||||||
|
as the calculations used longs instead of doubles! Paul Harrington reported.
|
||||||
|
|
||||||
|
- The SSL SocketIsDead() checks weren't good enough (as expected really), so I
|
||||||
|
had to add a generic internal try-it-out system. If the request on a re-used
|
||||||
|
connection seems to fail, then we go back and get a new (fresh) connection
|
||||||
|
and re-tries the request on that instead. It kind of makes the
|
||||||
|
SocketIsDead() check obsolete, but I think it is a quicker way for those
|
||||||
|
cases where it actually discovers that the connection is dead.
|
||||||
|
|
||||||
|
- When fixing the above, I noticed that we did quite a few writes to sockets
|
||||||
|
in libcurl where we didn't check the return code (that it actually worked to
|
||||||
|
send the data). With the new "attempted request" system we must detect those
|
||||||
|
situations so I went over a bunch of functions, changed return types and
|
||||||
|
added checks for what they actually return.
|
||||||
|
|
||||||
|
Version 7.9.1-pre6
|
||||||
|
|
||||||
|
Daniel (31 October 2001)
|
||||||
|
- Paul Harrington detected a problem with persistant SSL connections. Or to be
|
||||||
|
more exact, we didn't properly detect that the connection was dead and then
|
||||||
|
a second connection would try to re-use it wrongly. The solution to this
|
||||||
|
problem is still not very clear and I'm working on it. One OpenSSL insider
|
||||||
|
said there is no way to know if the SSL connection is alive or not without
|
||||||
|
actually trying an operation.
|
||||||
|
|
||||||
|
Daniel (30 October 2001)
|
||||||
|
- If a cookie was read from a file, it could accidentally strdup() a NULL
|
||||||
|
pointer. Paul Harrington reported. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/cookie.c.diff?r1=1.25&r2=1.26]
|
||||||
|
|
||||||
|
- The MANUAL file now documents -t correctly. I also fixed the -T description
|
||||||
|
in the curl.1 man page.
|
||||||
|
|
||||||
|
Daniel (29 October 2001)
|
||||||
|
- John Janssen found out that curl_formadd was missing in the libcurl.def file
|
||||||
|
and that the docs stated the wrong return type for the function.
|
||||||
|
|
||||||
|
- Andr<64>s Garc<72>a found a bug with multiple files in the curl_formadd() function,
|
||||||
|
that I removed with this patch [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/formdata.c.diff?r1=1.25&r2=1.26].
|
||||||
|
|
||||||
|
- Kevin Roth brought another patch that moved the cygwin package files to the
|
||||||
|
packages/Win32/cygwin directory.
|
||||||
|
|
||||||
|
- A bug in the connection re-use logic made repeated requests to the same FTP
|
||||||
|
server (when using name+pasword in the URL) sometimes use more than one
|
||||||
|
connection. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/url.c.diff?r1=1.166&r2=1.167]
|
||||||
|
|
||||||
|
- Moonesamy tracked down and fixed a problem with the new 7.9.1 connect
|
||||||
|
code. This corrected the error Kevin Roth reported on the 7.9.1-pre5 release
|
||||||
|
(test 19)...
|
||||||
|
[http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/connect.c.diff?r1=1.13&r2=1.14]
|
||||||
|
|
||||||
|
Daniel (26 October 2001)
|
||||||
|
- Added test28 which verifies that "Location:"-following works even if the
|
||||||
|
contents is separated with more than one space.
|
||||||
|
|
||||||
|
Daniel (25 October 2001)
|
||||||
|
- Ramana Mokkapati pointed out that LDAP transfers would 'hang' after the
|
||||||
|
correct data has been output.
|
||||||
|
|
||||||
|
Version 7.9.1-pre5
|
||||||
|
|
||||||
|
Daniel (24 October 2001)
|
||||||
|
- T. Bharath found a memory leak in the cookie engine. When we update a cookie
|
||||||
|
that we already knew about, we lost a chunk of memory in the progress... The
|
||||||
|
brand new test case 27 now tests for this occurrence. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/cookie.c.diff?r1=1.24&r2=1.25]
|
||||||
|
|
||||||
|
Daniel (23 October 2001)
|
||||||
|
- pack_hostent() didn't properly align some pointers, so at least SPARC CPUs
|
||||||
|
would core. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/hostip.c.diff?r1=1.34&r2=1.35]
|
||||||
|
|
||||||
|
Daniel (22 October 2001)
|
||||||
|
- Tom Benoist reported that this SGI IRIX compiler didn't handle indented
|
||||||
|
preprocessor instructions, so they're no longer in the source code!
|
||||||
|
|
||||||
|
- Applied Kevin Roth's patches to make it easier to build cygwin packages from
|
||||||
|
the out-of-the-box curl release archives.
|
||||||
|
|
||||||
|
- I forgot to mention it below, but libcurl now closes connections that report
|
||||||
|
transfer failures. Unconditionally. This could be made more nicely in the
|
||||||
|
future if we set a flag or something that the connection is still good to be
|
||||||
|
used for the errors that know that for a fact. We have to close the
|
||||||
|
connection for the cases where we abort for example a HTTP transfer in the
|
||||||
|
middle, or otherwise we might re-use that connection later with lots of data
|
||||||
|
still being sent to us on it. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/transfer.c.diff?r1=1.63&r2=1.64]
|
||||||
|
|
||||||
|
Daniel (19 October 2001)
|
||||||
|
- CURLE_GOT_NOTHING is now returned when a HTTP server doesn't return
|
||||||
|
anything, not even a header. test case 37 was added to test for this.
|
||||||
|
|
||||||
|
- T. Bharath made curl_easy_duphandle() properly clone the cookie status as
|
||||||
|
well.
|
||||||
|
|
||||||
|
Version 7.9.1-pre4
|
||||||
|
|
||||||
|
Daniel (18 October 2001)
|
||||||
|
- CURLOPT_FAILONERROR, set with "curl --fail" no longer returns an error if
|
||||||
|
the HTTP return code is below 400.
|
||||||
|
|
||||||
|
Daniel (17 October 2001)
|
||||||
|
- The test suite now kills any running test http server when you re-start the
|
||||||
|
tests.
|
||||||
|
|
||||||
|
- We had to remove 'use strict' from two perl scripts, as the cygwin
|
||||||
|
adjustments didn't play nicely otherwise for some reason. Any perl wizard
|
||||||
|
out there who can put the scrict back and still make it run good on unix and
|
||||||
|
cygwin?
|
||||||
|
|
||||||
|
- A potential memory leak pointed out to us by Yanick Pelletier was removed.
|
||||||
|
It would occur when a http file transfer fails. [http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/curl/curl/lib/transfer.c.diff?r1=1.60&r2=1.61]
|
||||||
|
|
||||||
|
- The memory debugging system should no longer display anything to stderr
|
||||||
|
if the curl_memdebug() hasn't been used to explicitly say so. This makes it
|
||||||
|
easier to use the memory debug system and switch the logging on/off.
|
||||||
|
|
||||||
|
Daniel (16 October 2001)
|
||||||
|
- Kevin Roth provided fixes for building curl nicer in cygwin environments.
|
||||||
|
|
||||||
|
Daniel (12 October 2001)
|
||||||
|
- Cleaning up the progress meter/info code. The "current speed" is now more
|
||||||
|
accurate than before as we now use the true time spent between the measures,
|
||||||
|
and not just "assuming" every-second-update like before. The output should
|
||||||
|
now also be of the same width at all times, never to show "extra" zeroes on
|
||||||
|
the right edge.
|
||||||
|
|
||||||
|
- After talking about possible Location: bugs on the mailing list, I modified
|
||||||
|
the "absolute URL" checker in lib/transfer.c to be more strict when checking
|
||||||
|
if the redirected URL is absolute.
|
||||||
|
|
||||||
|
Daniel (11 October 2001)
|
||||||
|
- Kevin Roth provided patches that make the test suite run fine on Windows
|
||||||
|
2000 running cygwin.
|
||||||
|
|
||||||
|
Daniel (10 October 2001)
|
||||||
|
- Setting the -c or the CURLOPT_COOKIEJAR option now enables the cookie parser.
|
||||||
|
Previously -b or CURLOPT_COOKIEFILE was also required for the jar to work.
|
||||||
|
|
||||||
|
Version 7.9.1-pre3
|
||||||
|
|
||||||
|
Daniel (9 October 2001)
|
||||||
|
- Added a new option to the command line client: -0/--http1.0. It uses the new
|
||||||
|
libcurl option CURLOPT_HTTP_VERSION to request that libcurl uses HTTP 1.0
|
||||||
|
requests instead of the default version (1.1). It should only be used if you
|
||||||
|
really MUST do that because of a silly remote server.
|
||||||
|
|
||||||
|
- Renamed the 'TimeCond' typedef in curl/curl.h to use a 'curl_' prefix as
|
||||||
|
all public curl-symbols should.
|
||||||
|
|
||||||
|
- libcurl now explicitly ignores the SIGPIPE signal.
|
||||||
|
|
||||||
|
Daniel (8 October 2001)
|
||||||
|
- Kevin Roth's change to the cookie-jar comment (in the stored file) was
|
||||||
|
applied.
|
||||||
|
|
||||||
|
- Lucas Adamski's minor bug in the bind error code failf() was fixed.
|
||||||
|
|
||||||
|
Daniel (5 October 2001)
|
||||||
|
- Moonesamy fixed the Curl_connecthost() function to not give compiler errors
|
||||||
|
on a bunch of compilers, due to the argument named 'socket'.
|
||||||
|
|
||||||
|
- Moonesamy also provided updated VC++ makefiles and project files.
|
||||||
|
|
||||||
|
Version 7.9.1-pre2
|
||||||
|
|
||||||
|
Daniel (4 October 2001)
|
||||||
|
- Albert Chin provided a configure patch that makes the script detect proper
|
||||||
|
gethostbyname_r() method without actually running any code, only compiling
|
||||||
|
is necessary. This also removes the need of having a resolving 'localhost'
|
||||||
|
name.
|
||||||
|
|
||||||
|
- Found and removed memory leakage (name resolve data) in libcurl on
|
||||||
|
IPv6-enabled hosts. These could sneak through because we didn't have any
|
||||||
|
resource tracing on the IPv6-related functions. We do now.
|
||||||
|
|
||||||
|
Daniel (3 October 2001)
|
||||||
|
- Keith McGuigan patched away a (mainly Windows-) problem with the name
|
||||||
|
resolver data being kept in the static memory area, which is removed when a
|
||||||
|
thread is killed. The curl handle itself though perfectly handles being
|
||||||
|
passed between threads.
|
||||||
|
|
||||||
|
- Dirk Eddelbuettel reported an odd bug that turned out to be his proxy that
|
||||||
|
required an Authorization: header. Now, proxies are not supposed to require
|
||||||
|
that header, that is for true servers...
|
||||||
|
|
||||||
|
- I accidentally ruined Georg's curl_formadd(). Uh, bad me. Corrected now.
|
||||||
|
|
||||||
|
Version 7.9.1-pre1
|
||||||
|
|
||||||
|
Daniel (3 October 2001)
|
||||||
|
- Georg Huettenegger once again made an effort beyond the call of duty and not
|
||||||
|
only improved the curl_formadd() function, but also took care of adjusting
|
||||||
|
the curl command line client to use this new function instead of the
|
||||||
|
obsoleted curl_formparse.
|
||||||
|
|
||||||
|
Daniel (2 October 2001)
|
||||||
|
- Major fix in how libcurl does TCP connects. It now does non-blocking
|
||||||
|
connects to enable good timeouts without signals, and it now tries all IP
|
||||||
|
addresses for any given host (if it resolves more than one and the first
|
||||||
|
one(s) don't connect). Added a new source file 'connect.c' to deal with all
|
||||||
|
the TCP connect stuff.
|
||||||
|
|
||||||
|
- We now support IPv4-style IP-addresses in rfc2732-format, to better support
|
||||||
|
people writing scripts without knowing what address there is.
|
||||||
|
|
||||||
|
Daniel (28 September 2001)
|
||||||
|
- Cleanups in the FTP source code. Divided the code into even more smaller
|
||||||
|
functions and generally tried to make the differences between IPv4 and IPv6
|
||||||
|
get less noticable in the sources.
|
||||||
|
|
||||||
|
- If the remote file time is not readable/accessable/understood by libcurl,
|
||||||
|
libcurl now returns -1 in the CURLINFO_FILETIME data, not 0 as it previously
|
||||||
|
did. This should make curl not touch the file data unless there was a known
|
||||||
|
remote date when -R is used.
|
||||||
|
|
||||||
|
Daniel (27 September 2001)
|
||||||
|
- Working on getting non-blocking connects working platform independent. We
|
||||||
|
will also make curl try all IPs for a given host if the first one should
|
||||||
|
fail.
|
||||||
|
|
||||||
|
Daniel (26 September 2001)
|
||||||
|
- Kevin Roth provided a cookie example that proved the cookie jar
|
||||||
|
functionality wasn't working properly. I added test case 46 and made it
|
||||||
|
work.
|
||||||
|
|
||||||
|
Daniel (25 September 2001)
|
||||||
|
- J<>rn Hartroth updated the mingw32 makefiles.
|
||||||
|
|
||||||
|
Version 7.9
|
||||||
|
|
||||||
Daniel (23 September 2001)
|
Daniel (23 September 2001)
|
||||||
- Found and removed a 'socket leak' that would occur on IPv6 enabled hosts
|
- Found and removed a 'socket leak' that would occur on IPv6 enabled hosts
|
||||||
when FTP RETR failed.
|
when FTP RETR failed.
|
||||||
|
3
MITX.txt
3
MITX.txt
@@ -10,8 +10,7 @@ in the Software without restriction, including without limitation the rights
|
|||||||
to use, copy, modify, merge, publish, distribute, and/or sell copies of the
|
to use, copy, modify, merge, publish, distribute, and/or sell copies of the
|
||||||
Software, and to permit persons to whom the Software is furnished to do so,
|
Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
provided that the above copyright notice(s) and this permission notice appear
|
provided that the above copyright notice(s) and this permission notice appear
|
||||||
in all copies of the Software and that both the above copyright notice(s) and
|
in all copies of the Software.
|
||||||
this permission notice appear in supporting documentation.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
@@ -67,3 +67,9 @@ pkgadd:
|
|||||||
make install DESTDIR=`/bin/pwd`/packages/Solaris/root ; \
|
make install DESTDIR=`/bin/pwd`/packages/Solaris/root ; \
|
||||||
cat LEGAL MITX.txt MPL-1.1.txt > $(srcdir)/packages/Solaris/copyright ; \
|
cat LEGAL MITX.txt MPL-1.1.txt > $(srcdir)/packages/Solaris/copyright ; \
|
||||||
cd $(srcdir)/packages/Solaris && $(MAKE) package
|
cd $(srcdir)/packages/Solaris && $(MAKE) package
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build a cygwin binary tarball installation file
|
||||||
|
# resulting .tar.bz2 file will end up at packages/Win32/cygwin
|
||||||
|
cygwinbin:
|
||||||
|
$(MAKE) -C packages/Win32/cygwin cygwinbin
|
||||||
|
1
README
1
README
@@ -26,6 +26,7 @@ README
|
|||||||
The official download mirror sites are:
|
The official download mirror sites are:
|
||||||
|
|
||||||
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
|
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
|
||||||
|
Sweden -- ftp://cool.haxx.se/curl/
|
||||||
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
|
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
|
||||||
|
|
||||||
To download the very latest source off the CVS server do this:
|
To download the very latest source off the CVS server do this:
|
||||||
|
@@ -54,3 +54,11 @@
|
|||||||
|
|
||||||
/* Define if you have a working OpenSSL installation */
|
/* Define if you have a working OpenSSL installation */
|
||||||
#undef OPENSSL_ENABLED
|
#undef OPENSSL_ENABLED
|
||||||
|
|
||||||
|
/* Define the one correct non-blocking socket method below */
|
||||||
|
#undef HAVE_FIONBIO
|
||||||
|
#undef HAVE_IOCTLSOCKET
|
||||||
|
#undef HAVE_IOCTLSOCKET_CASE
|
||||||
|
#undef HAVE_O_NONBLOCK
|
||||||
|
#undef HAVE_DISABLED_NONBLOCKING
|
||||||
|
|
||||||
|
169
acinclude.m4
169
acinclude.m4
@@ -1,3 +1,107 @@
|
|||||||
|
dnl Check for how to set a socket to non-blocking state. There seems to exist
|
||||||
|
dnl four known different ways, with the one used almost everywhere being POSIX
|
||||||
|
dnl and XPG3, while the other different ways for different systems (old BSD,
|
||||||
|
dnl Windows and Amiga).
|
||||||
|
dnl
|
||||||
|
dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the
|
||||||
|
dnl O_NONBLOCK define is found but does not work. This condition is attempted
|
||||||
|
dnl to get caught in this script by using an excessive number of #ifdefs...
|
||||||
|
dnl
|
||||||
|
AC_DEFUN(CURL_CHECK_NONBLOCKING_SOCKET,
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING([non-blocking sockets style])
|
||||||
|
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
/* headers for O_NONBLOCK test */
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
],[
|
||||||
|
/* try to compile O_NONBLOCK */
|
||||||
|
|
||||||
|
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||||
|
# if defined(__SVR4) || defined(__srv4__)
|
||||||
|
# define PLATFORM_SOLARIS
|
||||||
|
# else
|
||||||
|
# define PLATFORM_SUNOS4
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
|
||||||
|
# define PLATFORM_AIX_V3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3)
|
||||||
|
#error "O_NONBLOCK does not work on this platform"
|
||||||
|
#endif
|
||||||
|
int socket;
|
||||||
|
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
],[
|
||||||
|
dnl the O_NONBLOCK test was fine
|
||||||
|
nonblock="O_NONBLOCK"
|
||||||
|
AC_DEFINE(HAVE_O_NONBLOCK)
|
||||||
|
],[
|
||||||
|
dnl the code was bad, try a different program now, test 2
|
||||||
|
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
/* headers for FIONBIO test */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stropts.h>
|
||||||
|
],[
|
||||||
|
/* FIONBIO source test */
|
||||||
|
int flags = ioctl(socket, FIONBIO, &flags);
|
||||||
|
],[
|
||||||
|
dnl FIONBIO test was good
|
||||||
|
nonblock="FIONBIO"
|
||||||
|
AC_DEFINE(HAVE_FIONBIO)
|
||||||
|
],[
|
||||||
|
dnl FIONBIO test was also bad
|
||||||
|
dnl the code was bad, try a different program now, test 3
|
||||||
|
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
/* headers for ioctlsocket test (cygwin?) */
|
||||||
|
#include <windows.h>
|
||||||
|
],[
|
||||||
|
/* ioctlsocket source code */
|
||||||
|
int flags = ioctlsocket(socket, FIONBIO, &flags);
|
||||||
|
],[
|
||||||
|
dnl ioctlsocket test was good
|
||||||
|
nonblock="ioctlsocket"
|
||||||
|
AC_DEFINE(HAVE_IOCTLSOCKET)
|
||||||
|
],[
|
||||||
|
dnl ioctlsocket didnt compile!
|
||||||
|
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
/* headers for IoctlSocket test (Amiga?) */
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
],[
|
||||||
|
/* IoctlSocket source code */
|
||||||
|
int flags = IoctlSocket(socket, FIONBIO, (long)1);
|
||||||
|
],[
|
||||||
|
dnl ioctlsocket test was good
|
||||||
|
nonblock="IoctlSocket"
|
||||||
|
AC_DEFINE(HAVE_IOCTLSOCKET_CASE)
|
||||||
|
],[
|
||||||
|
dnl ioctlsocket didnt compile!
|
||||||
|
nonblock="nada"
|
||||||
|
AC_DEFINE(HAVE_DISABLED_NONBLOCKING)
|
||||||
|
])
|
||||||
|
dnl end of forth test
|
||||||
|
|
||||||
|
])
|
||||||
|
dnl end of third test
|
||||||
|
|
||||||
|
])
|
||||||
|
dnl end of second test
|
||||||
|
|
||||||
|
])
|
||||||
|
dnl end of non-blocking try-compile test
|
||||||
|
AC_MSG_RESULT($nonblock)
|
||||||
|
|
||||||
|
if test "$nonblock" = "nada"; then
|
||||||
|
AC_MSG_WARN([non-block sockets disabled])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
dnl Check for socklen_t: historically on BSD it is an int, and in
|
dnl Check for socklen_t: historically on BSD it is an int, and in
|
||||||
dnl POSIX 1g it is a type of its own, but some platforms use different
|
dnl POSIX 1g it is a type of its own, but some platforms use different
|
||||||
dnl types for the argument to getsockopt, getpeername, etc. So we
|
dnl types for the argument to getsockopt, getpeername, etc. So we
|
||||||
@@ -142,7 +246,6 @@ AC_DEFUN(CURL_CHECK_INET_NTOA_R,
|
|||||||
AC_DEFINE(NEED_REENTRANT)
|
AC_DEFINE(NEED_REENTRANT)
|
||||||
AC_MSG_RESULT(yes)],
|
AC_MSG_RESULT(yes)],
|
||||||
AC_MSG_RESULT(no))])])
|
AC_MSG_RESULT(no))])])
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN(CURL_CHECK_GETHOSTBYADDR_R,
|
AC_DEFUN(CURL_CHECK_GETHOSTBYADDR_R,
|
||||||
@@ -220,8 +323,6 @@ rc = gethostbyaddr_r(address, length, type, &h,
|
|||||||
ac_cv_gethostbyaddr_args=8],[
|
ac_cv_gethostbyaddr_args=8],[
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
have_missing_r_funcs="$have_missing_r_funcs gethostbyaddr_r"])])])])])
|
have_missing_r_funcs="$have_missing_r_funcs gethostbyaddr_r"])])])])])
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
|
AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
|
||||||
@@ -229,28 +330,21 @@ AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
|
|||||||
dnl check for number of arguments to gethostbyname_r. it might take
|
dnl check for number of arguments to gethostbyname_r. it might take
|
||||||
dnl either 3, 5, or 6 arguments.
|
dnl either 3, 5, or 6 arguments.
|
||||||
AC_CHECK_FUNCS(gethostbyname_r,[
|
AC_CHECK_FUNCS(gethostbyname_r,[
|
||||||
AC_MSG_CHECKING(if gethostbyname_r takes 3 arguments)
|
AC_MSG_CHECKING([if gethostbyname_r takes 3 arguments])
|
||||||
AC_TRY_RUN([
|
AC_TRY_COMPILE([
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main () {
|
gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[
|
||||||
struct hostent h;
|
gethostbyname_r(NULL, NULL, NULL);],[
|
||||||
struct hostent_data hdata;
|
|
||||||
char *name = "localhost";
|
|
||||||
int rc;
|
|
||||||
memset(&h, 0, sizeof(struct hostent));
|
|
||||||
memset(&hdata, 0, sizeof(struct hostent_data));
|
|
||||||
rc = gethostbyname_r(name, &h, &hdata);
|
|
||||||
exit (rc != 0 ? 1 : 0); }],[
|
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
||||||
ac_cv_gethostbyname_args=3],[
|
ac_cv_gethostbyname_args=3],[
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
AC_MSG_CHECKING(if gethostbyname_r with -D_REENTRANT takes 3 arguments)
|
AC_MSG_CHECKING([if gethostbyname_r with -D_REENTRANT takes 3 arguments])
|
||||||
AC_TRY_RUN([
|
AC_TRY_COMPILE([
|
||||||
#define _REENTRANT
|
#define _REENTRANT
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -258,53 +352,34 @@ exit (rc != 0 ? 1 : 0); }],[
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main () {
|
gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[
|
||||||
struct hostent h;
|
gethostbyname_r(NULL, NULL, NULL);],[
|
||||||
struct hostent_data hdata;
|
|
||||||
char *name = "localhost";
|
|
||||||
int rc;
|
|
||||||
memset(&h, 0, sizeof(struct hostent));
|
|
||||||
memset(&hdata, 0, sizeof(struct hostent_data));
|
|
||||||
rc = gethostbyname_r(name, &h, &hdata);
|
|
||||||
exit (rc != 0 ? 1 : 0); }],[
|
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
||||||
AC_DEFINE(NEED_REENTRANT)
|
AC_DEFINE(NEED_REENTRANT)
|
||||||
ac_cv_gethostbyname_args=3],[
|
ac_cv_gethostbyname_args=3],[
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
AC_MSG_CHECKING(if gethostbyname_r takes 5 arguments)
|
AC_MSG_CHECKING([if gethostbyname_r takes 5 arguments])
|
||||||
AC_TRY_RUN([
|
AC_TRY_COMPILE([
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
int
|
struct hostent *
|
||||||
main () {
|
gethostbyname_r(const char *, struct hostent *, char *, int, int *);],[
|
||||||
struct hostent *hp;
|
gethostbyname_r(NULL, NULL, NULL, 0, NULL);],[
|
||||||
struct hostent h;
|
|
||||||
char *name = "localhost";
|
|
||||||
char buffer[8192];
|
|
||||||
int h_errno;
|
|
||||||
hp = gethostbyname_r(name, &h, buffer, 8192, &h_errno);
|
|
||||||
exit (hp == NULL ? 1 : 0); }],[
|
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_5)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_5)
|
||||||
ac_cv_gethostbyname_args=5],[
|
ac_cv_gethostbyname_args=5],[
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
AC_MSG_CHECKING(if gethostbyname_r takes 6 arguments)
|
AC_MSG_CHECKING([if gethostbyname_r takes 6 arguments])
|
||||||
AC_TRY_RUN([
|
AC_TRY_COMPILE([
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main () {
|
gethostbyname_r(const char *, struct hostent *, char *, size_t,
|
||||||
struct hostent h;
|
struct hostent **, int *);],[
|
||||||
struct hostent *hp;
|
gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL);],[
|
||||||
char *name = "localhost";
|
|
||||||
char buf[8192];
|
|
||||||
int rc;
|
|
||||||
int h_errno;
|
|
||||||
rc = gethostbyname_r(name, &h, buf, 8192, &hp, &h_errno);
|
|
||||||
exit (rc != 0 ? 1 : 0); }],[
|
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_6)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_6)
|
||||||
ac_cv_gethostbyname_args=6],[
|
ac_cv_gethostbyname_args=6],[
|
||||||
|
BIN
build_vms.com
BIN
build_vms.com
Binary file not shown.
@@ -5,9 +5,7 @@ die(){
|
|||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKEFILES=`find . -name Makefile.am | sed 's/\.am$//'`
|
automake || die "The command 'automake $MAKEFILES' failed"
|
||||||
|
|
||||||
automake $MAKEFILES || die "The command 'automake $MAKEFILES' failed"
|
|
||||||
aclocal || die "The command 'aclocal' failed"
|
aclocal || die "The command 'aclocal' failed"
|
||||||
autoheader || die "The command 'autoheader' failed"
|
autoheader || die "The command 'autoheader' failed"
|
||||||
autoconf || die "The command 'autoconf' failed"
|
autoconf || die "The command 'autoconf' failed"
|
||||||
|
34
configure.in
34
configure.in
@@ -1,9 +1,16 @@
|
|||||||
dnl $Id$
|
dnl $Id$
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
dnl Ensure that this file is processed with autoconf 2.50 or newer
|
||||||
|
dnl Don't even think about removing this check!
|
||||||
|
AC_PREREQ(2.50)
|
||||||
|
|
||||||
|
dnl First some basic init macros
|
||||||
AC_INIT
|
AC_INIT
|
||||||
AC_CONFIG_SRCDIR([lib/urldata.h])
|
AC_CONFIG_SRCDIR([lib/urldata.h])
|
||||||
AM_CONFIG_HEADER(config.h src/config.h)
|
AM_CONFIG_HEADER(config.h src/config.h)
|
||||||
|
|
||||||
|
dnl figure out the libcurl version
|
||||||
VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h`
|
VERSION=`sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' ${srcdir}/include/curl/curl.h`
|
||||||
AM_INIT_AUTOMAKE(curl,$VERSION)
|
AM_INIT_AUTOMAKE(curl,$VERSION)
|
||||||
|
|
||||||
@@ -38,6 +45,10 @@ AC_PROG_CC
|
|||||||
dnl check for how to do large files
|
dnl check for how to do large files
|
||||||
AC_SYS_LARGEFILE
|
AC_SYS_LARGEFILE
|
||||||
|
|
||||||
|
dnl check for cygwin stuff
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
|
||||||
|
dnl libtool setup
|
||||||
AM_PROG_LIBTOOL
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
dnl The install stuff has already been taken care of by the automake stuff
|
dnl The install stuff has already been taken care of by the automake stuff
|
||||||
@@ -158,6 +169,24 @@ AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(ucb, gethostname))
|
|||||||
dnl dl lib?
|
dnl dl lib?
|
||||||
AC_CHECK_FUNC(dlclose, , AC_CHECK_LIB(dl, dlopen))
|
AC_CHECK_FUNC(dlclose, , AC_CHECK_LIB(dl, dlopen))
|
||||||
|
|
||||||
|
dnl **********************************************************************
|
||||||
|
dnl Check how non-blocking sockets are set
|
||||||
|
dnl **********************************************************************
|
||||||
|
AC_ARG_ENABLE(nonblocking,
|
||||||
|
[ --enable-nonblocking Makes the script detect how to do it
|
||||||
|
--disable-nonblocking Makes the script disable non-blocking sockets],
|
||||||
|
[
|
||||||
|
if test "$enableval" = "no" ; then
|
||||||
|
AC_MSG_WARN([non-blocking sockets disabled])
|
||||||
|
AC_DEFINE(HAVE_DISABLED_NONBLOCKING)
|
||||||
|
else
|
||||||
|
CURL_CHECK_NONBLOCKING_SOCKET
|
||||||
|
fi
|
||||||
|
],
|
||||||
|
[
|
||||||
|
CURL_CHECK_NONBLOCKING_SOCKET
|
||||||
|
])
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
dnl Check for the random seed preferences
|
dnl Check for the random seed preferences
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
@@ -428,9 +457,6 @@ then
|
|||||||
Set to explicitly specify we don't want to use thread-safe functions)
|
Set to explicitly specify we don't want to use thread-safe functions)
|
||||||
else
|
else
|
||||||
|
|
||||||
dnl check that 'localhost' resolves first
|
|
||||||
CURL_CHECK_WORKING_RESOLVER
|
|
||||||
|
|
||||||
dnl dig around for gethostbyname_r()
|
dnl dig around for gethostbyname_r()
|
||||||
CURL_CHECK_GETHOSTBYNAME_R()
|
CURL_CHECK_GETHOSTBYNAME_R()
|
||||||
|
|
||||||
@@ -518,7 +544,6 @@ AC_CHECK_FUNCS( socket \
|
|||||||
strcmpi \
|
strcmpi \
|
||||||
gethostname \
|
gethostname \
|
||||||
gethostbyaddr \
|
gethostbyaddr \
|
||||||
getservbyname \
|
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
inet_addr \
|
inet_addr \
|
||||||
inet_ntoa \
|
inet_ntoa \
|
||||||
@@ -571,6 +596,7 @@ AC_CONFIG_FILES([Makefile \
|
|||||||
tests/data/Makefile \
|
tests/data/Makefile \
|
||||||
packages/Makefile \
|
packages/Makefile \
|
||||||
packages/Win32/Makefile \
|
packages/Win32/Makefile \
|
||||||
|
packages/Win32/cygwin/Makefile \
|
||||||
packages/Linux/Makefile \
|
packages/Linux/Makefile \
|
||||||
packages/Linux/RPM/Makefile \
|
packages/Linux/RPM/Makefile \
|
||||||
packages/Linux/RPM/curl.spec \
|
packages/Linux/RPM/curl.spec \
|
||||||
|
32
docs/FAQ
32
docs/FAQ
@@ -1,4 +1,4 @@
|
|||||||
Updated: August 23, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
Updated: November 1, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
||||||
_ _ ____ _
|
_ _ ____ _
|
||||||
___| | | | _ \| |
|
___| | | | _ \| |
|
||||||
/ __| | | | |_) | |
|
/ __| | | | |_) | |
|
||||||
@@ -36,6 +36,7 @@ FAQ
|
|||||||
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
|
3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
|
||||||
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
||||||
3.11 How do I POST with a different Content-Type?
|
3.11 How do I POST with a different Content-Type?
|
||||||
|
3.12 Why do FTP specific features over HTTP proxy fails?
|
||||||
|
|
||||||
4. Running Problems
|
4. Running Problems
|
||||||
4.1 Problems connecting to SSL servers.
|
4.1 Problems connecting to SSL servers.
|
||||||
@@ -96,10 +97,9 @@ FAQ
|
|||||||
|
|
||||||
1.3 What is cURL not?
|
1.3 What is cURL not?
|
||||||
|
|
||||||
Curl is *not*, I repeat, *not* a wget clone even though that is a very
|
Curl is *not* a wget clone even though that is a very common misconception.
|
||||||
common misconception. Never, during curl's development, have I intended curl
|
Never, during curl's development, have we intended curl to replace wget or
|
||||||
to replace wget or compete on its market. Curl is targeted at single-shot
|
compete on its market. Curl is targeted at single-shot file transfers.
|
||||||
file transfers.
|
|
||||||
|
|
||||||
Curl is not a web site mirroring program. If you wanna use curl to mirror
|
Curl is not a web site mirroring program. If you wanna use curl to mirror
|
||||||
something: fine, go ahead and write a script that wraps around curl to make
|
something: fine, go ahead and write a script that wraps around curl to make
|
||||||
@@ -134,7 +134,7 @@ FAQ
|
|||||||
|
|
||||||
* We focus on protocol related issues and improvements. If you wanna do more
|
* We focus on protocol related issues and improvements. If you wanna do more
|
||||||
magic with the supported protocols than curl currently does, chances are
|
magic with the supported protocols than curl currently does, chances are
|
||||||
big I will agree. If you wanna add more protocols, I may very well
|
big we will agree. If you wanna add more protocols, we may very well
|
||||||
agree.
|
agree.
|
||||||
|
|
||||||
* If you want someone else to make all the work while you wait for us to
|
* If you want someone else to make all the work while you wait for us to
|
||||||
@@ -375,6 +375,18 @@ FAQ
|
|||||||
|
|
||||||
curl -d "datatopost" -H "Content-Type: text/xml" [URL]
|
curl -d "datatopost" -H "Content-Type: text/xml" [URL]
|
||||||
|
|
||||||
|
3.12 Why do FTP specific features over HTTP proxy fail?
|
||||||
|
|
||||||
|
Because when you use a HTTP proxy, the protocol spoken on the network will
|
||||||
|
be HTTP, even if you specify a FTP URL. This effectively means that you
|
||||||
|
normally can't use FTP specific features such as ftp upload and ftp quote
|
||||||
|
etc.
|
||||||
|
|
||||||
|
There is one exception to this rule, and that is if you can "tunnel through"
|
||||||
|
the given HTTP proxy. Proxy tunneling is enabled with a special option (-P)
|
||||||
|
and is generally not available as proxy admins usuable disable tunneling to
|
||||||
|
other ports than 443 (which is used for HTTPS access through proxies).
|
||||||
|
|
||||||
4. Running Problems
|
4. Running Problems
|
||||||
|
|
||||||
4.1. Problems connecting to SSL servers.
|
4.1. Problems connecting to SSL servers.
|
||||||
@@ -573,13 +585,7 @@ FAQ
|
|||||||
|
|
||||||
5.4 Does libcurl do Winsock initialization on win32 systems?
|
5.4 Does libcurl do Winsock initialization on win32 systems?
|
||||||
|
|
||||||
No.
|
Yes (since 7.8.1) if told to in the curl_global_init() call.
|
||||||
|
|
||||||
On win32 systems, you need to init the winsock stuff manually, libcurl will
|
|
||||||
not do that for you. WSAStartup() and WSACleanup() should be used
|
|
||||||
accordingly. The reason for this is of course that a single application may
|
|
||||||
use several different libraries and parts, and there's no reason for every
|
|
||||||
single library to do this.
|
|
||||||
|
|
||||||
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
|
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
|
||||||
|
|
||||||
|
58
docs/INSTALL
58
docs/INSTALL
@@ -8,9 +8,12 @@
|
|||||||
|
|
||||||
Curl has been compiled and built on numerous different operating systems.
|
Curl has been compiled and built on numerous different operating systems.
|
||||||
|
|
||||||
If you're using Windows (95/98/NT/ME/2000 or whatever), VMS, RISC OS or OS/2,
|
Most systems build curl the same way (unix-style). Continue reading below for
|
||||||
you should continue reading from one the paragraphs further down. All other
|
more details if you're one of them.
|
||||||
systems should be capable of being installed as described below.
|
|
||||||
|
If you're using Windows (95/98/NT/ME/2000/XP or similar), VMS, RISC OS or OS/2
|
||||||
|
or cross-compile, you should continue reading from one the paragraphs further
|
||||||
|
down.
|
||||||
|
|
||||||
UNIX
|
UNIX
|
||||||
====
|
====
|
||||||
@@ -325,13 +328,50 @@ VMS
|
|||||||
13-jul-2001
|
13-jul-2001
|
||||||
N. Baggus
|
N. Baggus
|
||||||
|
|
||||||
|
CROSS COMPILE
|
||||||
|
=============
|
||||||
|
|
||||||
|
(This section was graciously brought to us by Jim Duey, 23-oct-2001)
|
||||||
|
|
||||||
|
Download and unpack the cURL package. Version should be 7.9.1 or later.
|
||||||
|
|
||||||
|
'cd' to the new directory. (ie. curl-7.9.1-pre4)
|
||||||
|
|
||||||
|
Set environment variables to point to the cross-compile toolchain and call
|
||||||
|
configure with any options you need. Be sure and specify the '--host' and
|
||||||
|
'--build' parameters at configuration time. The following script is an
|
||||||
|
example of cross-compiling for the IBM 405GP PowerPC processor using the
|
||||||
|
toolchain from MonteVista for Hardhat Linux.
|
||||||
|
|
||||||
|
(begin script)
|
||||||
|
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
|
||||||
|
export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
|
||||||
|
export AR=ppc_405-ar
|
||||||
|
export AS=ppc_405-as
|
||||||
|
export LD=ppc_405-ld
|
||||||
|
export RANLIB=ppc_405-ranlib
|
||||||
|
export CC=ppc_405-gcc
|
||||||
|
export NM=ppc_405-nm
|
||||||
|
|
||||||
|
configure --target=powerpc-hardhat-linux \
|
||||||
|
--host=powerpc-hardhat-linux \
|
||||||
|
--build=i586-pc-linux-gnu \
|
||||||
|
--prefix=/opt/hardhat/devkit/ppc/405/target/usr/local \
|
||||||
|
--exec-prefix=/usr/local
|
||||||
|
|
||||||
|
(end script)
|
||||||
|
|
||||||
|
The '--prefix' parameter specifies where cURL will be installed. If
|
||||||
|
'configure' completes successfully, do 'make' and 'make install' as usual.
|
||||||
|
|
||||||
PORTS
|
PORTS
|
||||||
=====
|
=====
|
||||||
This is a probably incomplete list of known hardware and operating systems
|
This is a probably incomplete list of known hardware and operating systems
|
||||||
that curl has been compiled for:
|
that curl has been compiled for:
|
||||||
|
|
||||||
- Ultrix 4.3a
|
|
||||||
- SINIX-Z v5
|
|
||||||
- Alpha DEC OSF 4
|
- Alpha DEC OSF 4
|
||||||
- Alpha Digital UNIX v3.2
|
- Alpha Digital UNIX v3.2
|
||||||
- Alpha FreeBSD 4.1
|
- Alpha FreeBSD 4.1
|
||||||
@@ -344,9 +384,14 @@ PORTS
|
|||||||
- PowerPC Darwin 1.0
|
- PowerPC Darwin 1.0
|
||||||
- PowerPC Linux
|
- PowerPC Linux
|
||||||
- PowerPC Mac OS X
|
- PowerPC Mac OS X
|
||||||
|
- SINIX-Z v5
|
||||||
- Sparc Linux
|
- Sparc Linux
|
||||||
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8
|
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8
|
||||||
- Sparc SunOS 4.1.X
|
- Sparc SunOS 4.1.X
|
||||||
|
- StrongARM (and other ARM) RISC OS 3.1, 4.02
|
||||||
|
- StrongARM Linux 2.4
|
||||||
|
- StrongARM NetBSD 1.4.1
|
||||||
|
- Ultrix 4.3a
|
||||||
- i386 BeOS
|
- i386 BeOS
|
||||||
- i386 FreeBSD
|
- i386 FreeBSD
|
||||||
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
|
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
|
||||||
@@ -359,8 +404,7 @@ PORTS
|
|||||||
- ia64 Linux 2.3.99
|
- ia64 Linux 2.3.99
|
||||||
- m68k AmigaOS 3
|
- m68k AmigaOS 3
|
||||||
- m68k OpenBSD
|
- m68k OpenBSD
|
||||||
- StrongARM NetBSD 1.4.1
|
- s390 Linux
|
||||||
- StrongARM (and other ARM) RISC OS 3.1, 4.02
|
|
||||||
|
|
||||||
OpenSSL
|
OpenSSL
|
||||||
=======
|
=======
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Updated for curl 7.8 on May 29, 2001
|
Updated for curl 7.9.1 on November 2, 2001
|
||||||
_ _ ____ _
|
_ _ ____ _
|
||||||
___| | | | _ \| |
|
___| | | | _ \| |
|
||||||
/ __| | | | |_) | |
|
/ __| | | | |_) | |
|
||||||
@@ -78,15 +78,15 @@ Library
|
|||||||
makes sure we stay absolutely platform independent.
|
makes sure we stay absolutely platform independent.
|
||||||
|
|
||||||
curl_easy_init() allocates an internal struct and makes some initializations.
|
curl_easy_init() allocates an internal struct and makes some initializations.
|
||||||
The returned handle does not reveal internals. This is the 'UrlData' struct
|
The returned handle does not reveal internals. This is the 'SessionHandle'
|
||||||
which works as a global "anchor" struct. All connections performed will get
|
struct which works as an "anchor" struct for all curl_easy functions. All
|
||||||
connect-specific data allocated that should be used for things related to
|
connections performed will get connect-specific data allocated that should be
|
||||||
particular connections/requests.
|
used for things related to particular connections/requests.
|
||||||
|
|
||||||
curl_easy_setopt() takes three arguments, where the option stuff must be
|
curl_easy_setopt() takes three arguments, where the option stuff must be
|
||||||
passed in pairs: the parameter-ID and the parameter-value. The list of
|
passed in pairs: the parameter-ID and the parameter-value. The list of
|
||||||
options is documented in the man page. This function mainly sets things in
|
options is documented in the man page. This function mainly sets things in
|
||||||
the 'UrlData' struct.
|
the 'SessionHandle' struct.
|
||||||
|
|
||||||
curl_easy_perform() does a whole lot of things:
|
curl_easy_perform() does a whole lot of things:
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ Library
|
|||||||
This function makes sure there's an allocated and initiated 'connectdata'
|
This function makes sure there's an allocated and initiated 'connectdata'
|
||||||
struct that is used for this particular connection only (although there may
|
struct that is used for this particular connection only (although there may
|
||||||
be several requests performed on the same connect). A bunch of things are
|
be several requests performed on the same connect). A bunch of things are
|
||||||
inited/inherited from the UrlData struct.
|
inited/inherited from the SessionHandle struct.
|
||||||
|
|
||||||
o Curl_do()
|
o Curl_do()
|
||||||
|
|
||||||
@@ -123,6 +123,13 @@ Library
|
|||||||
Curl_Transfer() function (in lib/transfer.c) to setup the transfer and
|
Curl_Transfer() function (in lib/transfer.c) to setup the transfer and
|
||||||
returns.
|
returns.
|
||||||
|
|
||||||
|
Starting in 7.9.1, if this DO function fails and the connection is being
|
||||||
|
re-used, libcurl will then close this connection, setup a new connection
|
||||||
|
and re-issue the DO request on that. This is because there is no way to be
|
||||||
|
perfectly sure that we have discovered a dead connection before the DO
|
||||||
|
function and thus we might wrongly be re-using a connection that was closed
|
||||||
|
by the remote peer.
|
||||||
|
|
||||||
o Transfer()
|
o Transfer()
|
||||||
|
|
||||||
Curl_perform() then calls Transfer() in lib/transfer.c that performs
|
Curl_perform() then calls Transfer() in lib/transfer.c that performs
|
||||||
@@ -144,7 +151,7 @@ Library
|
|||||||
o Curl_disconnect()
|
o Curl_disconnect()
|
||||||
|
|
||||||
When doing normal connections and transfers, no one ever tries to close any
|
When doing normal connections and transfers, no one ever tries to close any
|
||||||
connection so this is not normally called when curl_easy_perform() is
|
connections so this is not normally called when curl_easy_perform() is
|
||||||
used. This function is only used when we are certain that no more transfers
|
used. This function is only used when we are certain that no more transfers
|
||||||
is going to be made on the connection. It can be also closed by force, or
|
is going to be made on the connection. It can be also closed by force, or
|
||||||
it can be called to make sure that libcurl doesn't keep too many
|
it can be called to make sure that libcurl doesn't keep too many
|
||||||
@@ -258,12 +265,12 @@ Persistent Connections
|
|||||||
The persistent connection support in libcurl requires some considerations on
|
The persistent connection support in libcurl requires some considerations on
|
||||||
how to do things inside of the library.
|
how to do things inside of the library.
|
||||||
|
|
||||||
o The 'UrlData' struct returned in the curl_easy_init() call must never
|
o The 'SessionHandle' struct returned in the curl_easy_init() call must never
|
||||||
hold connection-oriented data. It is meant to hold the root data as well
|
hold connection-oriented data. It is meant to hold the root data as well as
|
||||||
as all the options etc that the library-user may choose.
|
all the options etc that the library-user may choose.
|
||||||
o The 'UrlData' struct holds the "connection cache" (an array of pointers to
|
o The 'SessionHandle' struct holds the "connection cache" (an array of
|
||||||
'connectdata' structs). There's one connectdata struct allocated for each
|
pointers to 'connectdata' structs). There's one connectdata struct
|
||||||
connection that libcurl knows about.
|
allocated for each connection that libcurl knows about.
|
||||||
o This also enables the 'curl handle' to be reused on subsequent transfers,
|
o This also enables the 'curl handle' to be reused on subsequent transfers,
|
||||||
something that was illegal before libcurl 7.7.
|
something that was illegal before libcurl 7.7.
|
||||||
o When we are about to perform a transfer with curl_easy_perform(), we first
|
o When we are about to perform a transfer with curl_easy_perform(), we first
|
||||||
|
15
docs/MANUAL
15
docs/MANUAL
@@ -132,7 +132,7 @@ UPLOADING
|
|||||||
|
|
||||||
Upload all data on stdin to a specified ftp site:
|
Upload all data on stdin to a specified ftp site:
|
||||||
|
|
||||||
curl -t ftp://ftp.upload.com/myfile
|
curl -T - ftp://ftp.upload.com/myfile
|
||||||
|
|
||||||
Upload data from a specified file, login with user and password:
|
Upload data from a specified file, login with user and password:
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ UPLOADING
|
|||||||
|
|
||||||
Upload all data on stdin to a specified http site:
|
Upload all data on stdin to a specified http site:
|
||||||
|
|
||||||
curl -t http://www.upload.com/myfile
|
curl -T - http://www.upload.com/myfile
|
||||||
|
|
||||||
Note that the http server must've been configured to accept PUT before this
|
Note that the http server must've been configured to accept PUT before this
|
||||||
can be done successfully.
|
can be done successfully.
|
||||||
@@ -756,6 +756,17 @@ TELNET
|
|||||||
You might want the -N/--no-buffer option to switch off the buffered output
|
You might want the -N/--no-buffer option to switch off the buffered output
|
||||||
for slow connections or similar.
|
for slow connections or similar.
|
||||||
|
|
||||||
|
Pass options to the telnet protocol negotiation, by using the -t option. To
|
||||||
|
tell the server we use a vt100 terminal, try something like:
|
||||||
|
|
||||||
|
curl -tTTYPE=vt100 telnet://remote.server.com
|
||||||
|
|
||||||
|
Other interesting options for it -t include:
|
||||||
|
|
||||||
|
- XDISPLOC=<X display> Sets the X display location.
|
||||||
|
|
||||||
|
- NEW_ENV=<var,val> Sets an environment variable.
|
||||||
|
|
||||||
NOTE: the telnet protocol does not specify any way to login with a specified
|
NOTE: the telnet protocol does not specify any way to login with a specified
|
||||||
user and password so curl can't do that automatically. To do that, you need
|
user and password so curl can't do that automatically. To do that, you need
|
||||||
to track when the login prompt is received and send the username and
|
to track when the login prompt is received and send the username and
|
||||||
|
100
docs/TODO
100
docs/TODO
@@ -10,27 +10,42 @@ TODO
|
|||||||
send me patches that improve things! Also check the http://curl.haxx.se/dev
|
send me patches that improve things! Also check the http://curl.haxx.se/dev
|
||||||
web section for various development notes.
|
web section for various development notes.
|
||||||
|
|
||||||
To do in a future release (random order):
|
LIBCURL
|
||||||
|
|
||||||
* FTP ASCII upload does not follow RFC959 section 3.1.1.1:
|
|
||||||
"The sender converts the data from an internal character representation to
|
|
||||||
the standard 8-bit NVT-ASCII representation (see the Telnet
|
|
||||||
specification). The receiver will convert the data from the standard form
|
|
||||||
to his own internal form."
|
|
||||||
|
|
||||||
* Make the connect non-blocking so that timeouts work for connect in
|
|
||||||
multi-threaded programs
|
|
||||||
|
|
||||||
* Consider an interface to libcurl that allows applications to easier get to
|
* Consider an interface to libcurl that allows applications to easier get to
|
||||||
know what cookies that are sent back in the response headers.
|
know what cookies that are sent back in the response headers.
|
||||||
|
|
||||||
* HTTP PUT for files passed on stdin *OR* when the --crlf option is
|
* Make content encoding/decoding internally be made using a filter system.
|
||||||
used. Requires libcurl to send the file with chunked content
|
|
||||||
encoding. http://curl.haxx.se/dev/HTTP-PUT-stdin.txt
|
* The new 'multi' interface is being designed. Work out the details, start
|
||||||
|
implementing and write test applications!
|
||||||
|
[http://curl.haxx.se/dev/multi.h]
|
||||||
|
|
||||||
|
* Add a name resolve cache to libcurl to make repeated fetches to the same
|
||||||
|
host name (when persitancy isn't available) faster.
|
||||||
|
|
||||||
* Introduce another callback interface for upload/download that makes one
|
* Introduce another callback interface for upload/download that makes one
|
||||||
less copy of data and thus a faster operation.
|
less copy of data and thus a faster operation.
|
||||||
http://curl.haxx.se/dev/no_copy_callbacks.txt
|
[http://curl.haxx.se/dev/no_copy_callbacks.txt]
|
||||||
|
|
||||||
|
* Add configure options that disables certain protocols in libcurl to
|
||||||
|
decrease footprint. '--disable-[protocol]' where protocol is http, ftp,
|
||||||
|
telnet, ldap, dict or file.
|
||||||
|
|
||||||
|
* Add asynchronous name resolving. http://curl.haxx.se/dev/async-resolver.txt
|
||||||
|
|
||||||
|
DOCUMENTATION
|
||||||
|
|
||||||
|
* Document all CURLcode error codes, why they happen and what most likely
|
||||||
|
will make them not happen again.
|
||||||
|
|
||||||
|
FTP
|
||||||
|
|
||||||
|
* FTP ASCII upload does not follow RFC959 section 3.1.1.1: "The sender
|
||||||
|
converts the data from an internal character representation to the standard
|
||||||
|
8-bit NVT-ASCII representation (see the Telnet specification). The
|
||||||
|
receiver will convert the data from the standard form to his own internal
|
||||||
|
form."
|
||||||
|
|
||||||
* An option to only download remote FTP files if they're newer than the local
|
* An option to only download remote FTP files if they're newer than the local
|
||||||
one is a good idea, and it would fit right into the same syntax as the
|
one is a good idea, and it would fit right into the same syntax as the
|
||||||
@@ -39,33 +54,25 @@ To do in a future release (random order):
|
|||||||
|
|
||||||
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
|
* Suggested on the mailing list: CURLOPT_FTP_MKDIR...!
|
||||||
|
|
||||||
* Add configure options that disables certain protocols in libcurl to
|
* Always use the FTP SIZE command before downloading, as that makes it more
|
||||||
decrease footprint. '--disable-[protocol]' where protocol is http, ftp,
|
likely that we know the size when downloading. Some sites support SIZE but
|
||||||
telnet, ldap, dict or file.
|
don't show the size in the RETR response!
|
||||||
|
|
||||||
* Extend the test suite to include telnet. The telnet could just do ftp or
|
* Make FTP PASV work with IPv6 support. RFC 2428 "FTP Extensions for IPv6 and
|
||||||
http operations (for which we have test servers).
|
NATs" is interesting.
|
||||||
|
|
||||||
* Make TELNET work on windows!
|
HTTP
|
||||||
|
|
||||||
* Make curl's SSL layer option capable of using other free SSL libraries.
|
* HTTP PUT for files passed on stdin *OR* when the --crlf option is
|
||||||
Such as the Mozilla Security Services
|
used. Requires libcurl to send the file with chunked content
|
||||||
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
|
encoding. [http://curl.haxx.se/dev/HTTP-PUT-stdin.txt] When the filter
|
||||||
(http://gnutls.hellug.gr/)
|
system mentioned above gets real, it'll be a piece of cake to add.
|
||||||
|
|
||||||
* Add asynchronous name resolving, as this enables full timeout support for
|
|
||||||
fork() systems. http://curl.haxx.se/dev/async-resolver.txt
|
|
||||||
|
|
||||||
* Move non-URL related functions that are used by both the lib and the curl
|
|
||||||
application to a separate "portability lib".
|
|
||||||
|
|
||||||
* Add libcurl support/interfaces for more languages. C++ wrapper perhaps?
|
|
||||||
|
|
||||||
* "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get
|
* "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get
|
||||||
and decode compressed documents. There is the zlib that is pretty good at
|
and decode compressed documents. There is the zlib that is pretty good at
|
||||||
decompressing stuff. This work was started in October 1999 but halted again
|
decompressing stuff. This work was started in October 1999 but halted again
|
||||||
since it proved more work than we thought. It is still a good idea to
|
since it proved more work than we thought. It is still a good idea to
|
||||||
implement though.
|
implement though. This requires the filter system mentioned above.
|
||||||
|
|
||||||
* Authentication: NTLM. Support for that MS crap called NTLM
|
* Authentication: NTLM. Support for that MS crap called NTLM
|
||||||
authentication. MS proxies and servers sometime require that. Since that
|
authentication. MS proxies and servers sometime require that. Since that
|
||||||
@@ -88,10 +95,27 @@ To do in a future release (random order):
|
|||||||
sends the password in cleartext over the network, this "Digest" method uses
|
sends the password in cleartext over the network, this "Digest" method uses
|
||||||
a challange-response protocol which increases security quite a lot.
|
a challange-response protocol which increases security quite a lot.
|
||||||
|
|
||||||
* Other proxies
|
TELNET
|
||||||
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
|
|
||||||
|
|
||||||
* Full IPv6 Awareness and support. (This is partly done.) RFC 2428 "FTP
|
* Make TELNET work on windows98!
|
||||||
Extensions for IPv6 and NATs" is interesting. PORT should be replaced with
|
|
||||||
EPRT for IPv6 (done), and EPSV instead of PASV.
|
|
||||||
|
|
||||||
|
SSL
|
||||||
|
|
||||||
|
* Make curl's SSL layer option capable of using other free SSL libraries.
|
||||||
|
Such as the Mozilla Security Services
|
||||||
|
(http://www.mozilla.org/projects/security/pki/nss/) and GNUTLS
|
||||||
|
(http://gnutls.hellug.gr/)
|
||||||
|
|
||||||
|
LDAP
|
||||||
|
|
||||||
|
* Multiple URL requests don't work. [http://sourceforge.net/tracker/index.php?func=detail&aid=475407&group_id=976&atid=100976]
|
||||||
|
|
||||||
|
TEST SUITE
|
||||||
|
|
||||||
|
* Extend the test suite to include more protocols. The telnet could just do
|
||||||
|
ftp or http operations (for which we have test servers).
|
||||||
|
|
||||||
|
* Make the test suite work on more platforms. OpenBSD and Mac OS. Remove
|
||||||
|
fork()s and it should become even more portable.
|
||||||
|
|
||||||
|
* Introduce a test suite that tests libcurl better and more explicitly.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
Online: http://curl.haxx.se/docs/httpscripting.shtml
|
Online: http://curl.haxx.se/docs/httpscripting.shtml
|
||||||
Author: Daniel Stenberg <daniel@haxx.se>
|
Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
Date: August 20, 2001
|
Date: October 31, 2001
|
||||||
Version: 0.4
|
Version: 0.5
|
||||||
|
|
||||||
The Art Of Scripting HTTP Requests Using Curl
|
The Art Of Scripting HTTP Requests Using Curl
|
||||||
=============================================
|
=============================================
|
||||||
@@ -48,7 +48,7 @@ Version: 0.4
|
|||||||
2. URL
|
2. URL
|
||||||
|
|
||||||
The Uniform Resource Locator format is how you specify the address of a
|
The Uniform Resource Locator format is how you specify the address of a
|
||||||
particular resource on the internet. You know these, you've seen URLs like
|
particular resource on the Internet. You know these, you've seen URLs like
|
||||||
http://curl.haxx.se or https://yourbank.com a million times.
|
http://curl.haxx.se or https://yourbank.com a million times.
|
||||||
|
|
||||||
3. GET a page
|
3. GET a page
|
||||||
@@ -56,7 +56,7 @@ Version: 0.4
|
|||||||
The simplest and most common request/operation made using HTTP is to get a
|
The simplest and most common request/operation made using HTTP is to get a
|
||||||
URL. The URL could itself refer to a web page, an image or a file. The client
|
URL. The URL could itself refer to a web page, an image or a file. The client
|
||||||
issues a GET request to the server and receives the document it asked for.
|
issues a GET request to the server and receives the document it asked for.
|
||||||
If you isse the command line
|
If you issue the command line
|
||||||
|
|
||||||
curl http://curl.haxx.se
|
curl http://curl.haxx.se
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ Version: 0.4
|
|||||||
<input type=submit name=press value="OK">
|
<input type=submit name=press value="OK">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
In your favourite browser, this form will appear with a text box to fill in
|
In your favorite browser, this form will appear with a text box to fill in
|
||||||
and a press-button labeled "OK". If you fill in '1905' and press the OK
|
and a press-button labeled "OK". If you fill in '1905' and press the OK
|
||||||
button, your browser will then create a new URL to get for you. The URL will
|
button, your browser will then create a new URL to get for you. The URL will
|
||||||
get "junk.cgi?birthyear=1905&press=OK" appended to the path part of the
|
get "junk.cgi?birthyear=1905&press=OK" appended to the path part of the
|
||||||
@@ -136,8 +136,8 @@ Version: 0.4
|
|||||||
4.3 FILE UPLOAD POST
|
4.3 FILE UPLOAD POST
|
||||||
|
|
||||||
Back in late 1995 they defined a new way to post data over HTTP. It was
|
Back in late 1995 they defined a new way to post data over HTTP. It was
|
||||||
documented in the RFC 1867, why this method sometimes is refered to as
|
documented in the RFC 1867, why this method sometimes is referred to as
|
||||||
a rfc1867-posting.
|
a RFC1867-posting.
|
||||||
|
|
||||||
This method is mainly designed to better support file uploads. A form that
|
This method is mainly designed to better support file uploads. A form that
|
||||||
allows a user to upload a file could be written like this in HTML:
|
allows a user to upload a file could be written like this in HTML:
|
||||||
@@ -182,7 +182,7 @@ Version: 0.4
|
|||||||
way your browser does.
|
way your browser does.
|
||||||
|
|
||||||
An easy way to get to see this, is to save the HTML page with the form on
|
An easy way to get to see this, is to save the HTML page with the form on
|
||||||
your local disk, mofidy the 'method' to a GET, and press the submit button
|
your local disk, modify the 'method' to a GET, and press the submit button
|
||||||
(you could also change the action URL if you want to).
|
(you could also change the action URL if you want to).
|
||||||
|
|
||||||
You will then clearly see the data get appended to the URL, separated with a
|
You will then clearly see the data get appended to the URL, separated with a
|
||||||
@@ -214,7 +214,7 @@ Version: 0.4
|
|||||||
Sometimes your HTTP access is only available through the use of a HTTP
|
Sometimes your HTTP access is only available through the use of a HTTP
|
||||||
proxy. This seems to be especially common at various companies. A HTTP proxy
|
proxy. This seems to be especially common at various companies. A HTTP proxy
|
||||||
may require its own user and password to allow the client to get through to
|
may require its own user and password to allow the client to get through to
|
||||||
the internet. To specify those with curl, run something like:
|
the Internet. To specify those with curl, run something like:
|
||||||
|
|
||||||
curl -U proxyuser:proxypassword curl.haxx.se
|
curl -U proxyuser:proxypassword curl.haxx.se
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ Version: 0.4
|
|||||||
contents to the server, unless of course they are expired.
|
contents to the server, unless of course they are expired.
|
||||||
|
|
||||||
Many applications and servers use this method to connect a series of requests
|
Many applications and servers use this method to connect a series of requests
|
||||||
into a single logical session. To be able to use curl in such occations, we
|
into a single logical session. To be able to use curl in such occasions, we
|
||||||
must be able to record and send back cookies the way the web application
|
must be able to record and send back cookies the way the web application
|
||||||
expects them. The same way browsers deal with them.
|
expects them. The same way browsers deal with them.
|
||||||
|
|
||||||
@@ -325,6 +325,15 @@ Version: 0.4
|
|||||||
|
|
||||||
curl -b nada -L www.cookiesite.com
|
curl -b nada -L www.cookiesite.com
|
||||||
|
|
||||||
|
Curl has the ability to read and write cookie files that use the same file
|
||||||
|
format that Netscape and Mozilla do. It is a convenient way to share cookies
|
||||||
|
between browsers and automatic scripts. The -b switch automatically detects
|
||||||
|
if a given file is such a cookie file and parses it, and by using the
|
||||||
|
-c/--cookie-jar option you'll make curl write a new cookie file at the end of
|
||||||
|
an operation:
|
||||||
|
|
||||||
|
curl -b cookies.txt -c newcookies.txt www.cookiesite.com
|
||||||
|
|
||||||
11. HTTPS
|
11. HTTPS
|
||||||
|
|
||||||
There are a few ways to do secure HTTP transfers. The by far most common
|
There are a few ways to do secure HTTP transfers. The by far most common
|
||||||
@@ -349,7 +358,7 @@ Version: 0.4
|
|||||||
you need to enter the unlock-code before the certificate can be used by
|
you need to enter the unlock-code before the certificate can be used by
|
||||||
curl. The PIN-code can be specified on the command line or if not, entered
|
curl. The PIN-code can be specified on the command line or if not, entered
|
||||||
interactively when curl queries for it. Use a certificate with curl on a
|
interactively when curl queries for it. Use a certificate with curl on a
|
||||||
https server like:
|
HTTPS server like:
|
||||||
|
|
||||||
curl -E mycert.pem https://that.secure.server.com
|
curl -E mycert.pem https://that.secure.server.com
|
||||||
|
|
||||||
@@ -358,10 +367,12 @@ Version: 0.4
|
|||||||
RFC 2616 is a must to read if you want in-depth understanding of the HTTP
|
RFC 2616 is a must to read if you want in-depth understanding of the HTTP
|
||||||
protocol.
|
protocol.
|
||||||
|
|
||||||
RFC 2396 explains the URL syntax
|
RFC 2396 explains the URL syntax.
|
||||||
|
|
||||||
RFC 2109 defines how cookies are supposed to work.
|
RFC 2109 defines how cookies are supposed to work.
|
||||||
|
|
||||||
|
RFC 1867 defines the HTTP post upload format.
|
||||||
|
|
||||||
http://www.openssl.org is the home of the OpenSSL project
|
http://www.openssl.org is the home of the OpenSSL project
|
||||||
|
|
||||||
http://curl.haxx.se is the home of the cURL project
|
http://curl.haxx.se is the home of the cURL project
|
||||||
|
27
docs/curl.1
27
docs/curl.1
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man curl.1
|
.\" nroff -man curl.1
|
||||||
.\" Written by Daniel Stenberg
|
.\" Written by Daniel Stenberg
|
||||||
.\"
|
.\"
|
||||||
.TH curl 1 "12 Sep 2001" "Curl 7.9" "Curl Manual"
|
.TH curl 1 "30 Oct 2001" "Curl 7.9.1" "Curl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
|
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
|
||||||
HTTPS syntax.
|
HTTPS syntax.
|
||||||
@@ -485,14 +485,15 @@ XDISPLOC=<X display> Sets the X display location.
|
|||||||
|
|
||||||
NEW_ENV=<var,val> Sets an environment variable.
|
NEW_ENV=<var,val> Sets an environment variable.
|
||||||
.IP "-T/--upload-file <file>"
|
.IP "-T/--upload-file <file>"
|
||||||
Like -t, but this transfers the specified local file. If there is no
|
This transfers the specified local file to the remote URL. If there is no file
|
||||||
file part in the specified URL, Curl will append the local file
|
part in the specified URL, Curl will append the local file name. NOTE that you
|
||||||
name. NOTE that you must use a trailing / on the last directory to
|
must use a trailing / on the last directory to really prove to Curl that there
|
||||||
really prove to Curl that there is no file name or curl will
|
is no file name or curl will think that your last directory name is the remote
|
||||||
think that your last directory name is the remote file name to
|
file name to use. That will most likely cause the upload operation to fail. If
|
||||||
use. That will most likely cause the upload operation to fail. If
|
|
||||||
this is used on a http(s) server, the PUT command will be used.
|
this is used on a http(s) server, the PUT command will be used.
|
||||||
|
|
||||||
|
Use the file name "-" (a single dash) to use stdin instead of a given file.
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-u/--user <user:password>"
|
.IP "-u/--user <user:password>"
|
||||||
Specify user and password to use when fetching. See README.curl for detailed
|
Specify user and password to use when fetching. See README.curl for detailed
|
||||||
@@ -589,8 +590,13 @@ The average upload speed that curl measured for the complete upload.
|
|||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-x/--proxy <proxyhost[:port]>"
|
.IP "-x/--proxy <proxyhost[:port]>"
|
||||||
Use specified proxy. If the port number is not specified, it is assumed at
|
Use specified HTTP proxy. If the port number is not specified, it is assumed
|
||||||
port 1080.
|
at port 1080.
|
||||||
|
|
||||||
|
\fBNote\fP that all operations that are performed over a HTTP proxy will
|
||||||
|
transparantly be converted to HTTP. It means that certain protocol specific
|
||||||
|
operations might not be available. This is not the case if you can tunnel
|
||||||
|
through the proxy, as done with the \fI-p/--proxytunnel\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 "-X/--request <command>"
|
.IP "-X/--request <command>"
|
||||||
@@ -638,6 +644,9 @@ Forces curl to use SSL version 3 when negotiating with a remote SSL server.
|
|||||||
.IP "-2/--sslv2"
|
.IP "-2/--sslv2"
|
||||||
(HTTPS)
|
(HTTPS)
|
||||||
Forces curl to use SSL version 2 when negotiating with a remote SSL server.
|
Forces curl to use SSL version 2 when negotiating with a remote SSL server.
|
||||||
|
.IP "-0/--http1.0"
|
||||||
|
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its
|
||||||
|
internally preferred: HTTP 1.1.
|
||||||
.IP "-#/--progress-bar"
|
.IP "-#/--progress-bar"
|
||||||
Make curl display progress information as a progress bar instead of the
|
Make curl display progress information as a progress bar instead of the
|
||||||
default statistics.
|
default statistics.
|
||||||
|
@@ -2,83 +2,84 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_setopt 3 "12 Sep 2001" "libcurl 7.9" "libcurl Manual"
|
.TH curl_easy_setopt 3 "11 Oct 2001" "libcurl 7.9.1" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_setopt - Set curl easy-session options
|
curl_easy_setopt - Set curl easy-session options
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
.sp
|
|
||||||
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);"
|
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
curl_easy_setopt() is called to tell libcurl how to behave in a number of
|
curl_easy_setopt() is used to tell libcurl how to behave. Most operations in
|
||||||
ways. Most operations in libcurl have default actions, and by using the
|
libcurl have default actions, and by using the appropriate options to
|
||||||
appropriate options you can make them behave differently (as documented). All
|
\fIcurl_easy_setopt\fP, you can change them. All options are set with the
|
||||||
options are set with the
|
\fIoption\fP followed by a \fIparameter\fP. That parameter can be a long, a
|
||||||
.I option
|
function pointer or an object pointer, all depending on what the specific
|
||||||
followed by a parameter. That parameter can be a long, a function pointer or
|
option expects. Read this manual carefully as bad input values may cause
|
||||||
an object pointer, all depending on what the option in question expects. Read
|
libcurl to behave badly! You can only set one option in each function call. A
|
||||||
this manual carefully as bad input values may cause libcurl to behave badly!
|
typical application uses many curl_easy_setopt() calls in the setup phase.
|
||||||
You can only set one option in each function call. A typical application uses
|
|
||||||
many curl_easy_setopt() calls in the setup phase.
|
|
||||||
|
|
||||||
NOTE: strings passed to libcurl as 'char *' arguments, will not be copied by
|
\fBNOTE:\fP strings passed to libcurl as 'char *' arguments, will not be
|
||||||
the library. Instead you should keep them available until libcurl no longer
|
copied by the library. Instead you should keep them available until libcurl no
|
||||||
needs them. Failing to do so will cause very odd behaviour or even crashes.
|
longer needs them. Failing to do so will cause very odd behavior or even
|
||||||
|
crashes.
|
||||||
|
|
||||||
More note: the options set with this function call are valid for the
|
\fBNOTE2:\fP options set with this function call are valid for the forthcoming
|
||||||
forthcoming data transfers that are performed when you invoke
|
data transfers that are performed when you invoke \fIcurl_easy_perform\fP.
|
||||||
.I curl_easy_perform .
|
|
||||||
The options are not in any way reset between transfers, so if you want
|
The options are not in any way reset between transfers, so if you want
|
||||||
subsequent transfers with different options, you must change them between the
|
subsequent transfers with different options, you must change them between the
|
||||||
transfers.
|
transfers.
|
||||||
|
|
||||||
The
|
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
|
||||||
.I "handle"
|
\fIcurl_easy_duphandle(3)\fP call.
|
||||||
is the return code from the
|
|
||||||
.I "curl_easy_init"
|
|
||||||
call.
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
These options are in a bit of random order, but you'll figure it out!
|
The options are listed in a sort of random order, but you'll figure it out!
|
||||||
.TP 0.8i
|
.TP 0.8i
|
||||||
.B CURLOPT_FILE
|
.B CURLOPT_FILE
|
||||||
Data pointer to pass to file write function. Note that if you specify the
|
Data pointer to pass to the file write function. Note that if you specify the
|
||||||
.I CURLOPT_WRITEFUNCTION
|
\fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you
|
||||||
, this is the pointer you'll get as input. If you don't use a callback, you
|
don't use a callback, you must pass a 'FILE *' as libcurl will pass this to
|
||||||
must pass a 'FILE *' as libcurl passes it to fwrite() when writing data.
|
fwrite() when writing data.
|
||||||
|
|
||||||
NOTE: If you're using libcurl as a win32 DLL, you MUST use the
|
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use the
|
||||||
\fICURLOPT_WRITEFUNCTION\fP if you set this option.
|
\fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
|
||||||
|
crashes.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_WRITEFUNCTION
|
.B CURLOPT_WRITEFUNCTION
|
||||||
Function pointer that should match the following prototype:
|
Function pointer that should match the following prototype: \fBsize_t
|
||||||
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);"
|
function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This
|
||||||
This function gets called by libcurl as soon as there is received data that
|
function gets called by libcurl as soon as there is data available to pass
|
||||||
needs to be written down. The size of the data pointed to by \fIptr\fP is
|
available that needs to be saved. The size of the data pointed to by \fIptr\fP
|
||||||
\fIsize\fP multiplied with \fInmemb\fP. Return the number of bytes actually
|
is \fIsize\fP multiplied with \fInmemb\fP. Return the number of bytes
|
||||||
written or return -1 to signal error to the library (it will cause it to abort
|
actually taken care of. If that amount differs from the amount passed to your
|
||||||
the transfer with CURLE_WRITE_ERROR).
|
function, it'll signal an error to the library and it will abort the transfer
|
||||||
|
and return \fICURLE_WRITE_ERROR\fP.
|
||||||
|
|
||||||
Set the \fIstream\fP argument with the \fBCURLOPT_FILE\fP option.
|
Set the \fIstream\fP argument with the \fBCURLOPT_FILE\fP option.
|
||||||
|
|
||||||
|
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but
|
||||||
|
you cannot possibly make any assumptions. It may be one byte, it may be
|
||||||
|
thousands.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_INFILE
|
.B CURLOPT_INFILE
|
||||||
Data pointer to pass to the file read function. Note that if you specify the
|
Data pointer to pass to the file read function. Note that if you specify the
|
||||||
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
|
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
|
||||||
don't specify a read callback, this must be a valid FILE *.
|
don't specify a read callback, this must be a valid FILE *.
|
||||||
|
|
||||||
NOTE: If you're using libcurl as a win32 DLL, you MUST use a
|
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use a
|
||||||
\fICURLOPT_READFUNCTION\fP if you set this option.
|
\fICURLOPT_READFUNCTION\fP if you set this option.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_READFUNCTION
|
.B CURLOPT_READFUNCTION
|
||||||
Function pointer that should match the following prototype:
|
Function pointer that should match the following prototype: \fBsize_t
|
||||||
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);"
|
function( void *ptr, size_t size, size_t nmemb, void *stream);\fP This
|
||||||
This function gets called by libcurl as soon as it needs to read data in order
|
function gets called by libcurl as soon as it needs to read data in order to
|
||||||
to send it to the peer. The data area pointed at by the pointer \fIptr\fP may
|
send it to the peer. The data area pointed at by the pointer \fIptr\fP may be
|
||||||
be filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
|
filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
|
||||||
bytes. Your function must return the actual number of bytes that you stored in
|
bytes. Your function must return the actual number of bytes that you stored in
|
||||||
that memory area. Returning -1 will signal an error to the library and cause
|
that memory area. Returning -1 will signal an error to the library and cause
|
||||||
it to abort the current transfer immediately (with a CURLE_READ_ERROR return
|
it to abort the current transfer immediately (with a \fICURLE_READ_ERROR\fP
|
||||||
code).
|
return code).
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_INFILESIZE
|
.B CURLOPT_INFILESIZE
|
||||||
When uploading a file to a remote site, this option should be used to tell
|
When uploading a file to a remote site, this option should be used to tell
|
||||||
@@ -87,49 +88,67 @@ libcurl what the expected size of the infile is.
|
|||||||
.B CURLOPT_URL
|
.B CURLOPT_URL
|
||||||
The actual URL to deal with. The parameter should be a char * to a zero
|
The actual URL to deal with. The parameter should be a char * to a zero
|
||||||
terminated string. The string must remain present until curl no longer needs
|
terminated string. The string must remain present until curl no longer needs
|
||||||
it, as it doesn't copy the string. NOTE: this option is required to be set
|
it, as it doesn't copy the string.
|
||||||
before curl_easy_perform() is called.
|
|
||||||
|
\fBNOTE:\fP this option is (the only one) required to be set before
|
||||||
|
\fIcurl_easy_perform(3)\fP is called.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROXY
|
.B CURLOPT_PROXY
|
||||||
If you need libcurl to use a http proxy to access the outside world, set the
|
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
||||||
proxy string with this option. The parameter should be a char * to a zero
|
string holding the host name or dotted IP address. To specify port number in
|
||||||
terminated string. To specify port number in this string, append :[port] to
|
this string, append :[port] to the end of the host name. The proxy string may
|
||||||
the end of the host name. The proxy string may be prefixed with
|
be prefixed with [protocol]:// since any such prefix will be ignored. The
|
||||||
[protocol]:// since any such prefix will be ignored.
|
proxy's port number may optionally be specified with the separate option
|
||||||
|
\fICURLOPT_PROXYPORT\fP.
|
||||||
|
|
||||||
|
\fBNOTE:\fP when you tell the library to use a HTTP proxy, libcurl will
|
||||||
|
transparently convert operations to HTTP even if you specify a FTP URL
|
||||||
|
etc. This may have an impact on what other features of the library you can
|
||||||
|
use, such as CURLOPT_QUOTE and similar FTP specifics that don't work unless
|
||||||
|
you tunnel through the HTTP proxy. Such tunneling is activated with
|
||||||
|
\fICURLOPT_HTTPPROXYTUNNEL\fP.
|
||||||
|
|
||||||
|
\fBNOTE2:\fP libcurl respects the environment variables \fBhttp_proxy\fP,
|
||||||
|
\fBftp_proxy\fP, \fBall_proxy\fP etc, if any of those is set.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROXYPORT
|
.B CURLOPT_PROXYPORT
|
||||||
Set this long with this option to set the proxy port to use unless it is
|
Pass a long with this option to set the proxy port to connect to unless it is
|
||||||
specified in the proxy string CURLOPT_PROXY.
|
specified in the proxy string \fICURLOPT_PROXY\fP.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HTTPPROXYTUNNEL
|
.B CURLOPT_HTTPPROXYTUNNEL
|
||||||
Set the parameter to non-zero to get the library to tunnel all non-HTTP
|
Set the parameter to non-zero to get the library to tunnel all operations
|
||||||
operations through the given HTTP proxy. Do note that there is a big
|
through a given HTTP proxy. Note that there is a big difference between using
|
||||||
difference to use a proxy and to tunnel through it. If you don't know what
|
a proxy and to tunnel through it. If you don't know what this means, you
|
||||||
this means, you probably don't want this tunnel option. (Added in libcurl 7.3)
|
probably don't want this tunneling option. (Added in libcurl 7.3)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_VERBOSE
|
.B CURLOPT_VERBOSE
|
||||||
Set the parameter to non-zero to get the library to display a lot of verbose
|
Set the parameter to non-zero to get the library to display a lot of verbose
|
||||||
information about its operations. Very useful for libcurl and/or protocl
|
information about its operations. Very useful for libcurl and/or protocol
|
||||||
debugging and understanding.
|
debugging and understanding.
|
||||||
|
|
||||||
|
You hardly ever want this set in production use, you will almost always want
|
||||||
|
this when you debug/report problems.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HEADER
|
.B CURLOPT_HEADER
|
||||||
A non-zero parameter tells the library to include the header in the
|
A non-zero parameter tells the library to include the header in the body
|
||||||
output. This is only relevant for protocols that actually has a header
|
output. This is only relevant for protocols that actually have headers
|
||||||
preceeding the data (like HTTP).
|
preceding the data (like HTTP).
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_NOPROGRESS
|
.B CURLOPT_NOPROGRESS
|
||||||
A non-zero parameter tells the library to shut of the built-in progress meter
|
A non-zero parameter tells the library to shut of the built-in progress meter
|
||||||
completely. (NOTE: future versions of the lib is likely to not have any
|
completely.
|
||||||
built-in progress meter at all).
|
|
||||||
|
\fBNOTE:\fP future versions of libcurl is likely to not have any built-in
|
||||||
|
progress meter at all.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_NOBODY
|
.B CURLOPT_NOBODY
|
||||||
A non-zero parameter tells the library to not include the body-part in the
|
A non-zero parameter tells the library to not include the body-part in the
|
||||||
output. This is only relevant for protocols that have a separate header and
|
output. This is only relevant for protocols that have separate header and body
|
||||||
body part.
|
parts.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FAILONERROR
|
.B CURLOPT_FAILONERROR
|
||||||
A non-zero parameter tells the library to fail silently if the HTTP code
|
A non-zero parameter tells the library to fail silently if the HTTP code
|
||||||
returned is equal or larger than 300. The default action would be to return
|
returned is equal to or larger than 300. The default action would be to return
|
||||||
the page normally, ignoring that code.
|
the page normally, ignoring that code.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_UPLOAD
|
.B CURLOPT_UPLOAD
|
||||||
@@ -146,7 +165,7 @@ will imply this option.
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FTPLISTONLY
|
.B CURLOPT_FTPLISTONLY
|
||||||
A non-zero parameter tells the library to just list the names of an ftp
|
A non-zero parameter tells the library to just list the names of an ftp
|
||||||
directory, instead of doing a full directory listin that would include file
|
directory, instead of doing a full directory listing that would include file
|
||||||
sizes, dates etc.
|
sizes, dates etc.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FTPAPPEND
|
.B CURLOPT_FTPAPPEND
|
||||||
@@ -154,91 +173,108 @@ A non-zero parameter tells the library to append to the remote file instead of
|
|||||||
overwrite it. This is only useful when uploading to a ftp site.
|
overwrite it. This is only useful when uploading to a ftp site.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_NETRC
|
.B CURLOPT_NETRC
|
||||||
A non-zero parameter tells the library to scan your
|
A non-zero parameter tells the library to scan your \fI~/.netrc\fP file to
|
||||||
.I ~/.netrc
|
find user name and password for the remote site you are about to access. Only
|
||||||
file to find user name and password for the remote site you are about to
|
machine name, user name and password is taken into account (init macros and
|
||||||
access. Do note that curl does not verify that the file has the correct
|
similar things aren't supported).
|
||||||
properties set (as the standard unix ftp client does), and that only machine
|
|
||||||
name, user name and password is taken into account (init macros and similar
|
\fBNote:\fP libcurl does not verify that the file has the correct properties
|
||||||
things aren't supported).
|
set (as the standard Unix ftp client does). It should only be readable by
|
||||||
|
user.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FOLLOWLOCATION
|
.B CURLOPT_FOLLOWLOCATION
|
||||||
A non-zero parameter tells the library to follow any Location: header that the
|
A non-zero parameter tells the library to follow any Location: header that the
|
||||||
server sends as part of a HTTP header. NOTE that this means that the library
|
server sends as part of a HTTP header.
|
||||||
will resend the same request on the new location and follow new Location:
|
|
||||||
headers all the way until no more such headers are returned.
|
\fBNOTE:\fP this means that the library will re-send the same request on the
|
||||||
|
new location and follow new Location: headers all the way until no more such
|
||||||
|
headers are returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number
|
||||||
|
of redirects libcurl will follow.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_TRANSFERTEXT
|
.B CURLOPT_TRANSFERTEXT
|
||||||
A non-zero parameter tells the library to use ASCII mode for ftp transfers,
|
A non-zero parameter tells the library to use ASCII mode for ftp transfers,
|
||||||
instead of the default binary transfer. For LDAP transfers it gets the data in
|
instead of the default binary transfer. For LDAP transfers it gets the data in
|
||||||
plain text instead of HTML and for win32 systems it does not set the stdout to
|
plain text instead of HTML and for win32 systems it does not set the stdout to
|
||||||
binary mode. This option can be useable when transfering text data between
|
binary mode. This option can be usable when transferring text data between
|
||||||
system with different views on certain characters, such as newlines or
|
systems with different views on certain characters, such as newlines or
|
||||||
similar.
|
similar.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PUT
|
.B CURLOPT_PUT
|
||||||
A non-zero parameter tells the library to use HTTP PUT a file. The file to put
|
A non-zero parameter tells the library to use HTTP PUT to transfer data. The
|
||||||
must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
|
data should be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_USERPWD
|
.B CURLOPT_USERPWD
|
||||||
Pass a char * as parameter, which should be [username]:[password] to use for
|
Pass a char * as parameter, which should be [user name]:[password] to use for
|
||||||
the connection. If the password is left out, you will be prompted for it.
|
the connection. If the password is left out, you will be prompted for it.
|
||||||
|
\fICURLOPT_PASSWDFUNCTION\fP can be used to set your own prompt function.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROXYUSERPWD
|
.B CURLOPT_PROXYUSERPWD
|
||||||
Pass a char * as parameter, which should be [username]:[password] to use for
|
Pass a char * as parameter, which should be [user name]:[password] to use for
|
||||||
the connection to the HTTP proxy. If the password is left out, you will be
|
the connection to the HTTP proxy. If the password is left out, you will be
|
||||||
prompted for it.
|
prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can be used to set your own
|
||||||
|
prompt function.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_RANGE
|
.B CURLOPT_RANGE
|
||||||
Pass a char * as parameter, which should contain the specified range you
|
Pass a char * as parameter, which should contain the specified range you
|
||||||
want. It should be in the format "X-Y", where X or Y may be left out. HTTP
|
want. It should be in the format "X-Y", where X or Y may be left out. HTTP
|
||||||
transfers also support several intervals, separated with commas as in
|
transfers also support several intervals, separated with commas as in
|
||||||
.I "X-Y,N-M"
|
\fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP
|
||||||
. Using this kind of multiple intervals will cause the HTTP server to send the
|
server to send the response document in pieces (using standard MIME separation
|
||||||
response document in pieces.
|
techniques).
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_ERRORBUFFER
|
.B CURLOPT_ERRORBUFFER
|
||||||
Pass a char * to a buffer that the libcurl may store human readable error
|
Pass a char * to a buffer that the libcurl may store human readable error
|
||||||
messages in. This may be more helpful than just the return code from the
|
messages in. This may be more helpful than just the return code from the
|
||||||
library. The buffer must be at least CURL_ERROR_SIZE big.
|
library. The buffer must be at least CURL_ERROR_SIZE big.
|
||||||
|
|
||||||
|
\fBNote:\fP if the library does not return an error, the buffer may not have
|
||||||
|
been touched. Do not rely on the contents in those cases.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_TIMEOUT
|
.B CURLOPT_TIMEOUT
|
||||||
Pass a long as parameter containing the maximum time in seconds that you allow
|
Pass a long as parameter containing the maximum time in seconds that you allow
|
||||||
the libcurl transfer operation to take. Normally, name lookups can take a
|
the libcurl transfer operation to take. Normally, name lookups can take a
|
||||||
considerable time and limiting operations to less than a few minutes risk
|
considerable time and limiting operations to less than a few minutes risk
|
||||||
aborting perfectly normal operations. This option will cause curl to use the
|
aborting perfectly normal operations. This option will cause curl to use the
|
||||||
SIGALRM to enable timeouting system calls.
|
SIGALRM to enable time-outing system calls.
|
||||||
.B NOTE
|
|
||||||
that this does not work in multi-threaded programs!
|
\fBNOTE:\fP this does not work in Unix multi-threaded programs, as it uses
|
||||||
|
signals.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_POSTFIELDS
|
.B CURLOPT_POSTFIELDS
|
||||||
Pass a char * as parameter, which should be the full data to post in a HTTP
|
Pass a char * as parameter, which should be the full data to post in a HTTP
|
||||||
post operation. See also the CURLOPT_POST. Since 7.8, using CURLOPT_POSTFIELDS
|
post operation. This is a normal application/x-www-form-urlencoded kind, which
|
||||||
implies CURLOPT_POST.
|
is the most commonly used one by HTML forms. See also the CURLOPT_POST. Since
|
||||||
|
7.8, using CURLOPT_POSTFIELDS implies CURLOPT_POST.
|
||||||
|
|
||||||
|
\fBNote:\fP to make multipart/formdata posts (aka rfc1867-posts), check out
|
||||||
|
the \fICURLOPT_HTTPPOST\fP option.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_POSTFIELDSIZE
|
.B CURLOPT_POSTFIELDSIZE
|
||||||
If you want to post data to the server without letting libcurl do a strlen()
|
If you want to post data to the server without letting libcurl do a strlen()
|
||||||
to measure the data size, this option must be used. Also, when this option is
|
to measure the data size, this option must be used. When this option is used
|
||||||
used, you can post fully binary data which otherwise is likely to fail. If
|
you can post fully binary data, which otherwise is likely to fail. If this
|
||||||
this size is set to zero, the library will use strlen() to get the data
|
size is set to zero, the library will use strlen() to get the size. (Added in
|
||||||
size. (Added in libcurl 7.2)
|
libcurl 7.2)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_REFERER
|
.B CURLOPT_REFERER
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
Pass a pointer to a zero terminated string as parameter. It will be used to
|
||||||
set the referer: header in the http request sent to the remote server. This
|
set the Referer: header in the http request sent to the remote server. This
|
||||||
can be used to fool servers or scripts.
|
can be used to fool servers or scripts. You can also set any custom header
|
||||||
|
with \fICURLOPT_HTTPHEADER\fP.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_USERAGENT
|
.B CURLOPT_USERAGENT
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
Pass a pointer to a zero terminated string as parameter. It will be used to
|
||||||
set the user-agent: header in the http request sent to the remote server. This
|
set the User-Agent: header in the http request sent to the remote server. This
|
||||||
can be used to fool servers or scripts.
|
can be used to fool servers or scripts. You can also set any custom header
|
||||||
|
with \fICURLOPT_HTTPHEADER\fP.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FTPPORT
|
.B CURLOPT_FTPPORT
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
Pass a pointer to a zero terminated string as parameter. It will be used to
|
||||||
get the IP address to use for the ftp PORT instruction. The PORT instruction
|
get the IP address to use for the ftp PORT instruction. The PORT instruction
|
||||||
tells the remote server to connect to our specified IP address. The string may
|
tells the remote server to connect to our specified IP address. The string may
|
||||||
be a plain IP address, a host name, an network interface name (under unix) or
|
be a plain IP address, a host name, an network interface name (under Unix) or
|
||||||
just a '-' letter to let the library use your systems default IP address.
|
just a '-' letter to let the library use your systems default IP
|
||||||
|
address. Default FTP operations are passive, and thus won't use PORT.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_LOW_SPEED_LIMIT
|
.B CURLOPT_LOW_SPEED_LIMIT
|
||||||
Pass a long as parameter. It contains the transfer speed in bytes per second
|
Pass a long as parameter. It contains the transfer speed in bytes per second
|
||||||
@@ -261,82 +297,71 @@ set a cookie in the http request. The format of the string should be
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HTTPHEADER
|
.B CURLOPT_HTTPHEADER
|
||||||
Pass a pointer to a linked list of HTTP headers to pass to the server in your
|
Pass a pointer to a linked list of HTTP headers to pass to the server in your
|
||||||
HTTP request. The linked list should be a fully valid list of 'struct
|
HTTP request. The linked list should be a fully valid list of \fBstruct
|
||||||
curl_slist' structs properly filled in. Use
|
curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to
|
||||||
.I curl_slist_append(3)
|
create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire
|
||||||
to create the list and
|
list. If you add a header that is otherwise generated and used by libcurl
|
||||||
.I curl_slist_free_all(3)
|
internally, your added one will be used instead. If you add a header with no
|
||||||
to clean up an entire list. If you add a header that is otherwise generated
|
contents as in 'Accept:' (no data on the right side of the colon), the
|
||||||
and used by libcurl internally, your added one will be used instead. If you
|
internally used header will get disabled. Thus, using this option you can add
|
||||||
add a header with no contents as in 'Accept:', the internally used header will
|
new headers, replace internal headers and remove internal headers.
|
||||||
just get disabled. Thus, using this option you can add new headers, replace
|
|
||||||
internal headers and remove internal headers.
|
\fBNOTE:\fPThe most commonly replaced headers have "shortcuts" in the options
|
||||||
|
CURLOPT_COOKIE, CURLOPT_USERAGENT and CURLOPT_REFERER.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HTTPPOST
|
.B CURLOPT_HTTPPOST
|
||||||
Tells libcurl you want a multipart/formdata HTTP POST to be made and you
|
Tells libcurl you want a multipart/formdata HTTP POST to be made and you
|
||||||
instruct what data to pass on to the server. Pass a pointer to a linked list
|
instruct what data to pass on to the server. Pass a pointer to a linked list
|
||||||
of HTTP post structs as parameter. The linked list should be a fully valid
|
of HTTP post structs as parameter. The linked list should be a fully valid
|
||||||
list of 'struct HttpPost' structs properly filled in. The best and most
|
list of 'struct HttpPost' structs properly filled in. The best and most
|
||||||
elegant way to do this, is to use
|
elegant way to do this, is to use \fIcurl_formadd(3)\fP as documented. The
|
||||||
.I curl_formadd(3)
|
data in this list must remained intact until you close this curl handle again
|
||||||
as documented. The data in this list must remained intact until you close this
|
with \fIcurl_easy_cleanup(3)\fP.
|
||||||
curl handle again with curl_easy_cleanup().
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSLCERT
|
.B CURLOPT_SSLCERT
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the file name of your certficicate in PEM format.
|
the file name of your certificate in PEM format.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSLCERTPASSWD
|
.B CURLOPT_SSLCERTPASSWD
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used as
|
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||||
the password required to use the CURLOPT_SSLCERT certificate. If the password
|
the password required to use the CURLOPT_SSLCERT certificate. If the password
|
||||||
is not supplied, you will be prompted for it.
|
is not supplied, you will be prompted for it. \fICURLOPT_PASSWDFUNCTION\fP can
|
||||||
|
be used to set your own prompt function.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_CRLF
|
.B CURLOPT_CRLF
|
||||||
Convert unix newlines to CRLF newlines on FTP uploads.
|
Convert Unix newlines to CRLF newlines on FTP uploads.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_QUOTE
|
.B CURLOPT_QUOTE
|
||||||
Pass a pointer to a linked list of FTP commands to pass to the server prior to
|
Pass a pointer to a linked list of FTP commands to pass to the server prior to
|
||||||
your ftp request. The linked list should be a fully valid list of 'struct
|
your ftp request. The linked list should be a fully valid list of 'struct
|
||||||
curl_slist' structs properly filled in. Use
|
curl_slist' structs properly filled in. Use \fIcurl_slist_append(3)\fP to
|
||||||
.I curl_slist_append(3)
|
append strings (commands) to the list, and clear the entire list afterwards
|
||||||
to append strings (commands) to the list, and clear the entire list afterwards
|
with \fIcurl_slist_free_all(3)\fP.
|
||||||
with
|
|
||||||
.I curl_slist_free_all(3)
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_POSTQUOTE
|
.B CURLOPT_POSTQUOTE
|
||||||
Pass a pointer to a linked list of FTP commands to pass to the server after
|
Pass a pointer to a linked list of FTP commands to pass to the server after
|
||||||
your ftp transfer request. The linked list should be a fully valid list of
|
your ftp transfer request. The linked list should be a fully valid list of
|
||||||
struct curl_slist structs properly filled in as described for
|
struct curl_slist structs properly filled in as described for
|
||||||
.I "CURLOPT_QUOTE"
|
\fICURLOPT_QUOTE\fP.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_WRITEHEADER
|
.B CURLOPT_WRITEHEADER
|
||||||
Pass a pointer to be used to write the header part of the received data to. If
|
Pass a pointer to be used to write the header part of the received data to. If
|
||||||
you don't use a callback to take care of the writing, this must be a FILE
|
you don't use your own callback to take care of the writing, this must be a
|
||||||
*. The headers are guaranteed to be written one-by-one and only complete lines
|
valid FILE *. See also the \fICURLOPT_HEADERFUNCTION\fP option below on how to set a
|
||||||
are written. Parsing headers should be easy enough using this. See also the
|
custom get-all-headers callback.
|
||||||
\fICURLOPT_HEADERFUNCTION\fP option.
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HEADERFUNCTION
|
.B CURLOPT_HEADERFUNCTION
|
||||||
Function pointer that should match the following prototype:
|
Function pointer that should match the following prototype: \fIsize_t
|
||||||
.BI "size_t function( void *ptr, size_t size, size_t nmemb, void *stream);"
|
function( void *ptr, size_t size, size_t nmemb, void *stream);\fP. This
|
||||||
This function gets called by libcurl as soon as there is received header data
|
function gets called by libcurl as soon as there is received header data that
|
||||||
that needs to be written down. The function will be called once for each
|
needs to be written down. The headers are guaranteed to be written one-by-one
|
||||||
header with a complete header line in each invoke. The size of the data
|
and only complete lines are written. Parsing headers should be easy enough
|
||||||
pointed to by
|
using this. The size of the data pointed to by \fIptr\fP is \fIsize\fP
|
||||||
.I ptr
|
multiplied with \fInmemb\fP. The pointer named \fIstream\fP will be the one
|
||||||
is
|
you passed to libcurl with the \fICURLOPT_WRITEHEADER\fP option. Return the
|
||||||
.I size
|
number of bytes actually written or return -1 to signal error to the library
|
||||||
multiplied with
|
(it will cause it to abort the transfer with a \fICURLE_WRITE_ERROR\fP return
|
||||||
.I nmemb.
|
code). (Added in libcurl 7.7.2)
|
||||||
The pointer named
|
|
||||||
.I stream
|
|
||||||
will be the one you passed to libcurl with the
|
|
||||||
.I CURLOPT_WRITEHEADER
|
|
||||||
option.
|
|
||||||
Return the number of bytes actually written or return -1 to signal error to
|
|
||||||
the library (it will cause it to abort the transfer with a
|
|
||||||
.I CURLE_WRITE_ERROR
|
|
||||||
return code). (Added in libcurl 7.7.2)
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_COOKIEFILE
|
.B CURLOPT_COOKIEFILE
|
||||||
Pass a pointer to a zero terminated string as parameter. It should contain the
|
Pass a pointer to a zero terminated string as parameter. It should contain the
|
||||||
@@ -347,12 +372,12 @@ file.
|
|||||||
.B CURLOPT_SSLVERSION
|
.B 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
|
||||||
3. By default, the SSL library will try to solve this by itself although some
|
3. By default, the SSL library will try to solve this by itself although some
|
||||||
servers make this difficult why you at times will have to use this option.
|
servers make this difficult why you at times may have to use this option.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_TIMECONDITION
|
.B CURLOPT_TIMECONDITION
|
||||||
Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is
|
Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is
|
||||||
treated. You can set this parameter to TIMECOND_IFMODSINCE or
|
treated. You can set this parameter to TIMECOND_IFMODSINCE or
|
||||||
TIMECOND_IFUNMODSINCE. This is aa HTTP-only feature. (TBD)
|
TIMECOND_IFUNMODSINCE. This is a HTTP-only feature. (TBD)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_TIMEVALUE
|
.B 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,
|
||||||
@@ -362,8 +387,8 @@ isn't used, it will be TIMECOND_IFMODSINCE by default.
|
|||||||
.B CURLOPT_CUSTOMREQUEST
|
.B CURLOPT_CUSTOMREQUEST
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be user
|
Pass a pointer to a zero terminated string as parameter. It will be user
|
||||||
instead of GET or HEAD when doing the HTTP request. This is useful for doing
|
instead of GET or HEAD when doing the HTTP request. This is useful for doing
|
||||||
DELETE or other more obscure HTTP requests. Don't do this at will, make sure
|
DELETE or other more or less obscure HTTP requests. Don't do this at will,
|
||||||
your server supports the command first.
|
make sure your server supports the command first.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_STDERR
|
.B CURLOPT_STDERR
|
||||||
Pass a FILE * as parameter. This is the stream to use instead of stderr
|
Pass a FILE * as parameter. This is the stream to use instead of stderr
|
||||||
@@ -381,29 +406,18 @@ krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
|
|||||||
will be used. Set the string to NULL to disable kerberos4. The kerberos
|
will be used. Set the string to NULL to disable kerberos4. The kerberos
|
||||||
support only works for FTP. (Added in libcurl 7.3)
|
support only works for FTP. (Added in libcurl 7.3)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_WRITEINFO
|
|
||||||
(NOT PRESENT IN 7.4 or later!)
|
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
|
||||||
report information after a successful request. This string may contain
|
|
||||||
variables that will be substituted by their contents when output. Described
|
|
||||||
elsewhere.
|
|
||||||
.TP
|
|
||||||
.B CURLOPT_PROGRESSFUNCTION
|
.B CURLOPT_PROGRESSFUNCTION
|
||||||
Function pointer that should match the
|
Function pointer that should match the \fIcurl_progress_callback\fP prototype
|
||||||
.BI curl_progress_callback
|
found in \fI<curl/curl.h>\fP. This function gets called by libcurl instead of
|
||||||
prototype found in
|
its internal equivalent with a frequent interval during data transfer.
|
||||||
.I <curl/curl.h>
|
Unknown/unused argument values will be set to zero (like if you only download
|
||||||
This function gets called by libcurl instead of its internal
|
data, the upload size will remain 0). Returning a non-zero value from this
|
||||||
equivalent. Unknown/unused argument values will be set to zero (like if you
|
callback will cause libcurl to abort the transfer and return
|
||||||
only download data, the upload size will remain 0). Returning a non-zero value
|
\fICURLE_ABORTED_BY_CALLBACK\fP.
|
||||||
from this callback will cause libcurl to abort the transfer and return
|
|
||||||
CURLE_ABORTED_BY_CALLBACK.
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROGRESSDATA
|
.B CURLOPT_PROGRESSDATA
|
||||||
Pass a pointer that will be untouched by libcurl and passed as the first
|
Pass a pointer that will be untouched by libcurl and passed as the first
|
||||||
argument in the progress callback set with
|
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
|
||||||
.I CURLOPT_PROGRESSFUNCTION
|
|
||||||
.
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSL_VERIFYPEER
|
.B CURLOPT_SSL_VERIFYPEER
|
||||||
Pass a long that is set to a non-zero value to make curl verify the peer's
|
Pass a long that is set to a non-zero value to make curl verify the peer's
|
||||||
@@ -416,67 +430,66 @@ verify the peer with. This only makes sense when used in combination with the
|
|||||||
CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2)
|
CURLOPT_SSL_VERIFYPEER option. (Added in 7.4.2)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PASSWDFUNCTION
|
.B CURLOPT_PASSWDFUNCTION
|
||||||
Pass a pointer to a curl_passwd_callback function that will then be called
|
Pass a pointer to a \fIcurl_passwd_callback\fP function that will be called
|
||||||
instead of the internal one if libcurl requests a password. The function must
|
instead of the internal one if libcurl requests a password. The function must
|
||||||
match this prototype:
|
match this prototype: \fBint my_getpass(void *client, char *prompt, char*
|
||||||
.BI "int my_getpass(void *client, char *prompt, char* buffer, int buflen );"
|
buffer, int buflen );\fP. If set to NULL, it equals to making the function
|
||||||
If set to NULL, it equals to making the function always fail. If the function
|
always fail. If the function returns a non-zero value, it will abort the
|
||||||
returns a non-zero value, it will abort the operation and an error
|
operation and an error (CURLE_BAD_PASSWORD_ENTERED) will be returned.
|
||||||
(CURLE_BAD_PASSWORD_ENTERED) will be returned.
|
\fIclient\fP is a generic pointer, see \fICURLOPT_PASSWDDATA\fP. \fIprompt\fP
|
||||||
.I client
|
|
||||||
is a generic pointer, see CURLOPT_PASSWDDATA.
|
|
||||||
.I prompt
|
|
||||||
is a zero-terminated string that is text that prefixes the input request.
|
is a zero-terminated string that is text that prefixes the input request.
|
||||||
.I buffer
|
\fIbuffer\fP is a pointer to data where the entered password should be stored
|
||||||
is a pointer to data where the entered password should be stored and
|
and \fIbuflen\fP is the maximum number of bytes that may be written in the
|
||||||
.I buflen
|
buffer. (Added in 7.4.2)
|
||||||
is the maximum number of bytes that may be written in the buffer.
|
|
||||||
(Added in 7.4.2)
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PASSWDDATA
|
.B CURLOPT_PASSWDDATA
|
||||||
Pass a void * to whatever data you want. The passed pointer will be the first
|
Pass a void * to whatever data you want. The passed pointer will be the first
|
||||||
argument sent to the specifed CURLOPT_PASSWDFUNCTION function. (Added in
|
argument sent to the specifed \fICURLOPT_PASSWDFUNCTION\fP function. (Added in
|
||||||
7.4.2)
|
7.4.2)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FILETIME
|
.B CURLOPT_FILETIME
|
||||||
Pass a long. If it is a non-zero value, libcurl will attempt to get the
|
Pass a long. If it is a non-zero value, libcurl will attempt to get the
|
||||||
modification date of the remote document in this operation. This requires that
|
modification date of the remote document in this operation. This requires that
|
||||||
the remote server sends the time or replies to a time querying command. The
|
the remote server sends the time or replies to a time querying command. The
|
||||||
curl_easy_getinfo() function with the CURLINFO_FILETIME argument can be used
|
\fIcurl_easy_getinfo(3)\fP function with the \fICURLINFO_FILETIME\fP argument
|
||||||
after a transfer to extract the received time (if any). (Added in 7.5)
|
can be used after a transfer to extract the received time (if any). (Added in
|
||||||
|
7.5)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_MAXREDIRS
|
.B CURLOPT_MAXREDIRS
|
||||||
Pass a long. The set number will be the redirection limit. If that many
|
Pass a long. The set number will be the redirection limit. If that many
|
||||||
redirections have been followed, the next redirect will cause an error. This
|
redirections have been followed, the next redirect will cause an error
|
||||||
option only makes sense if the CURLOPT_FOLLOWLOCATION is used at the same
|
(\fICURLE_TOO_MANY_REDIRECTS\fP). This option only makes sense if the
|
||||||
time. (Added in 7.5)
|
\fICURLOPT_FOLLOWLOCATION\fP is used at the same time. (Added in 7.5)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_MAXCONNECTS
|
.B CURLOPT_MAXCONNECTS
|
||||||
Pass a long. The set number will be the persistant connection cache size. The
|
Pass a long. The set number will be the persistant connection cache size. The
|
||||||
set amount will be the maximum amount of simultaneous connections that libcurl
|
set amount will be the maximum amount of simultaneous connections that libcurl
|
||||||
may cache between file transfers. Default is 5, and there isn't much point in
|
may cache between file transfers. Default is 5, and there isn't much point in
|
||||||
changing this value unless you are perfectly aware of how this work and
|
changing this value unless you are perfectly aware of how this work and
|
||||||
changes libcurl's behaviour. Note: if you have already performed transfers
|
changes libcurl's behaviour.
|
||||||
with this curl handle, setting a smaller MAXCONNECTS than before may cause
|
|
||||||
open connections to unnecessarily get closed. (Added in 7.7)
|
\fBNOTE:\fP if you already have performed transfers with this curl handle,
|
||||||
|
setting a smaller MAXCONNECTS than before may cause open connections to get
|
||||||
|
closed unnecessarily. (Added in 7.7)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_CLOSEPOLICY
|
.B CURLOPT_CLOSEPOLICY
|
||||||
Pass a long. This option sets what policy libcurl should use when the
|
Pass a long. This option sets what policy libcurl should use when the
|
||||||
connection cache is filled and one of the open connections has to be closed to
|
connection cache is filled and one of the open connections has to be closed to
|
||||||
make room for a new connection. This must be one of the CURLCLOSEPOLICY_*
|
make room for a new connection. This must be one of the CURLCLOSEPOLICY_*
|
||||||
defines. Use CURLCLOSEPOLICY_LEAST_RECENTLY_USED to make libcurl close the
|
defines. Use \fICURLCLOSEPOLICY_LEAST_RECENTLY_USED\fP to make libcurl close
|
||||||
connection that was least recently used, that connection is also least likely
|
the connection that was least recently used, that connection is also least
|
||||||
to be capable of re-use. Use CURLCLOSEPOLICY_OLDEST to make libcurl close the
|
likely to be capable of re-use. Use \fICURLCLOSEPOLICY_OLDEST\fP to make
|
||||||
oldest connection, the one that was created first among the ones in the
|
libcurl close the oldest connection, the one that was created first among the
|
||||||
connection cache. The other close policies are not support yet. (Added in 7.7)
|
ones in the connection cache. The other close policies are not support
|
||||||
|
yet. (Added in 7.7)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FRESH_CONNECT
|
.B CURLOPT_FRESH_CONNECT
|
||||||
Pass a long. Set to non-zero to make the next transfer use a new connection by
|
Pass a long. Set to non-zero to make the next transfer use a new (fresh)
|
||||||
force. If the connection cache is full before this connection, one of the
|
connection by force. If the connection cache is full before this connection,
|
||||||
existinf connections will be closed as according to the set policy. This
|
one of the existing connections will be closed as according to the selected or
|
||||||
option should be used with caution and only if you understand what it
|
default policy. This option should be used with caution and only if you
|
||||||
does. Set to 0 to have libcurl attempt re-use of an existing connection.
|
understand what it does. Set this to 0 to have libcurl attempt re-using an
|
||||||
(Added in 7.7)
|
existing connection (default behavior). (Added in 7.7)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_FORBID_REUSE
|
.B CURLOPT_FORBID_REUSE
|
||||||
Pass a long. Set to non-zero to make the next transfer explicitly close the
|
Pass a long. Set to non-zero to make the next transfer explicitly close the
|
||||||
@@ -484,7 +497,7 @@ connection when done. Normally, libcurl keep all connections alive when done
|
|||||||
with one transfer in case there comes a succeeding one that can re-use them.
|
with one transfer in case there comes a succeeding one that can re-use them.
|
||||||
This option should be used with caution and only if you understand what it
|
This option should be used with caution and only if you understand what it
|
||||||
does. Set to 0 to have libcurl keep the connection open for possibly later
|
does. Set to 0 to have libcurl keep the connection open for possibly later
|
||||||
re-use. (Added in 7.7)
|
re-use (default behavior). (Added in 7.7)
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_RANDOM_FILE
|
.B CURLOPT_RANDOM_FILE
|
||||||
Pass a char * to a zero terminated file name. The file will be used to read
|
Pass a char * to a zero terminated file name. The file will be used to read
|
||||||
@@ -500,11 +513,10 @@ Pass a long. It should contain the maximum time in seconds that you allow the
|
|||||||
connection to the server to take. This only limits the connection phase, once
|
connection to the server to take. This only limits the connection phase, once
|
||||||
it has connected, this option is of no more use. Set to zero to disable
|
it has connected, this option is of no more use. Set to zero to disable
|
||||||
connection timeout (it will then only timeout on the system's internal
|
connection timeout (it will then only timeout on the system's internal
|
||||||
timeouts). See also the
|
timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
|
||||||
.I CURLOPT_TIMEOUT
|
|
||||||
option.
|
\fBNOTE:\fP this does not work in unix multi-threaded programs, as it uses
|
||||||
.B NOTE
|
signals.
|
||||||
that this does not work in multi-threaded programs!
|
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_HTTPGET
|
.B CURLOPT_HTTPGET
|
||||||
Pass a long. If the long is non-zero, this forces the HTTP request to get back
|
Pass a long. If the long is non-zero, this forces the HTTP request to get back
|
||||||
@@ -518,8 +530,8 @@ the provided hostname. (Added in 7.8.1)
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_COOKIEJAR
|
.B CURLOPT_COOKIEJAR
|
||||||
Pass a file name as char *, zero terminated. This will make libcurl dump all
|
Pass a file name as char *, zero terminated. This will make libcurl dump all
|
||||||
internally known cookies to the specified file when curl_easy_cleanup() is
|
internally known cookies to the specified file when \fIcurl_easy_cleanup(3)\fP
|
||||||
called. If no cookies are known, no file will be created. Specify "-" to
|
is called. If no cookies are known, no file will be created. Specify "-" to
|
||||||
instead have the cookies written to stdout.
|
instead have the cookies written to stdout.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_SSL_CIPHER_LIST
|
.B CURLOPT_SSL_CIPHER_LIST
|
||||||
@@ -531,14 +543,15 @@ be used as operators. Valid examples of cipher lists include 'RC4-SHA',
|
|||||||
\'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
|
\'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
|
||||||
compile OpenSSL.
|
compile OpenSSL.
|
||||||
|
|
||||||
You'll find all details about cipher lists on this URL:
|
You'll find more details about cipher lists on this URL:
|
||||||
.I http://www.openssl.org/docs/apps/ciphers.html
|
\fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
|
||||||
.PP
|
.PP
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
0 means the option was set properly, non-zero means an error as
|
CURLE_OK (zero) means that the option was set properly, non-zero means an
|
||||||
.I <curl/curl.h>
|
error occurred as \fI<curl/curl.h>\fP defines.
|
||||||
defines
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR curl_easy_init "(3), " curl_easy_cleanup "(3), "
|
.BR curl_easy_init "(3), " curl_easy_cleanup "(3), "
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Surely there are some, you tell me!
|
If you find any bugs, or just have questions, subscribe to one of the mailing
|
||||||
|
lists and post. We won't bite.
|
||||||
|
|
||||||
|
@@ -2,13 +2,13 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_formadd 3 "27 August 2001" "libcurl 7.9" "libcurl Manual"
|
.TH curl_formadd 3 "29 October 2001" "libcurl 7.9.1" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_formadd - add a section to a multipart/formdata HTTP POST
|
curl_formadd - add a section to a multipart/formdata HTTP POST
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/curl.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "CURLcode curl_formadd(struct HttpPost ** " firstitem,
|
.BI "int curl_formadd(struct HttpPost ** " firstitem,
|
||||||
.BI "struct HttpPost ** " lastitem, " ...);"
|
.BI "struct HttpPost ** " lastitem, " ...);"
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -17,49 +17,62 @@ HTTP POST (sometimes refered to as rfc1867-style posts). Append one section at
|
|||||||
a time until you've added all the sections you want included and then you pass
|
a time until you've added all the sections you want included and then you pass
|
||||||
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
|
the \fIfirstitem\fP pointer as parameter to \fBCURLOPT_HTTPPOST\fP.
|
||||||
\fIlastitem\fP is set after each call and on repeated invokes it should be
|
\fIlastitem\fP is set after each call and on repeated invokes it should be
|
||||||
left as set to allow repeated invokes to find the end of the list in a faster
|
left as set to allow repeated invokes to find the end of the list faster.
|
||||||
way.
|
|
||||||
|
|
||||||
After \fIlastitem\fP follow the real arguments that constitute the
|
After the \fIlastitem\fP pointer follow the real arguments. (If the following
|
||||||
new section (if the following description confuses you jump directly
|
description confuses you, jump directly to the examples):
|
||||||
to the examples):
|
|
||||||
|
|
||||||
CURLFORM_COPYNAME or CURLFORM_PTRNAME followed by a string is used for
|
\fBCURLFORM_COPYNAME\fP or \fBCURLFORM_PTRNAME\fP followed by a string is used
|
||||||
the name of the section. Optionally one may use CURLFORM_NAMELENGTH to
|
for the name of the section. Optionally one may use \fBCURLFORM_NAMELENGTH\fP
|
||||||
specify the length of the name (allowing null characters within the name).
|
to specify the length of the name (allowing null characters within the
|
||||||
|
name). All options that use the word COPY in their names copy the given
|
||||||
|
contents, while the ones with PTR in their names simply points to the (static)
|
||||||
|
data you must make sure remain until curl no longer needs it.
|
||||||
|
|
||||||
The three options for providing values are: CURLFORM_COPYCONTENTS,
|
The four options for providing values are: \fBCURLFORM_COPYCONTENTS\fP,
|
||||||
CURLFORM_PTRCONTENTS, or CURLFORM_FILE, followed by a char or void
|
\fBCURLFORM_PTRCONTENTS\fP, \fBCURLFORM_FILE\fP, or \fBCURLFORM_FILECONTENT\fP
|
||||||
pointer (allowed for PTRCONTENTS).
|
followed by a char or void pointer (allowed for PTRCONTENTS).
|
||||||
|
|
||||||
Other arguments may be CURLFORM_CONTENTTYPE if the
|
\fBCURLFORM_FILECONTENT\fP does a normal post like \fBCURLFORM_COPYCONTENTS\fP
|
||||||
user wishes to specify one (for FILE if no type is given the library
|
but the actual value is read from the filename given as a string.
|
||||||
tries to provide the correct one; for CONTENTS no Content-Type is sent
|
|
||||||
in this case)
|
|
||||||
|
|
||||||
For CURLFORM_PTRCONTENTS or CURLFORM_COPYNAME the user may also add
|
Other arguments may be \fBCURLFORM_CONTENTTYPE\fP if the user wishes to
|
||||||
CURLFORM_CONTENTSLENGTH followed by the length as a long (if not given
|
specify one (for FILE if no type is given the library tries to provide the
|
||||||
the library will use strlen to determine the length).
|
correct one; for CONTENTS no Content-Type is sent in this case).
|
||||||
|
|
||||||
For CURLFORM_FILE the user may send multiple files in one section by
|
For \fBCURLFORM_PTRCONTENTS\fP or \fBCURLFORM_COPYNAME\fP the user may also
|
||||||
providing multiple CURLFORM_FILE arguments each followed by the filename
|
add \fBCURLFORM_CONTENTSLENGTH\fP followed by the length as a long (if not
|
||||||
|
given the library will use strlen to determine the length).
|
||||||
|
|
||||||
|
For \fBCURLFORM_FILE\fP the user may send multiple files in one section by
|
||||||
|
providing multiple \fBCURLFORM_FILE\fP arguments each followed by the filename
|
||||||
(and each FILE is allowed to have a CONTENTTYPE).
|
(and each FILE is allowed to have a CONTENTTYPE).
|
||||||
|
|
||||||
The last argument always is CURLFORM_END.
|
Another possibility to send single or multiple files in one section is to use
|
||||||
|
\fBCURLFORM_ARRAY\fP that gets a struct curl_forms array pointer as its
|
||||||
|
value. Each structure element has a CURLformoption and a char pointer. For the
|
||||||
|
options only \fBCURLFORM_FILE\fP, \fBCURLFORM_CONTENTTYPE\fP, and
|
||||||
|
\fBCURLFORM_END\fP (that is used to determine the end of the array and thus
|
||||||
|
must be the option of the last and no other element of the curl_forms array)
|
||||||
|
are allowed. The effect of this parameter is the same as giving multiple
|
||||||
|
\fBCURLFORM_FILE\fP options possibly with \fBCURLFORM_CONTENTTYPE\fP after or
|
||||||
|
before each \fBCURLFORM_FILE\fP option.
|
||||||
|
|
||||||
|
The last argument in such an array must always be \fBCURLFORM_END\fP.
|
||||||
|
|
||||||
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
|
The pointers \fI*firstitem\fP and \fI*lastitem\fP should both be pointing to
|
||||||
NULL in the first call to this function. All list-data will be allocated by
|
NULL in the first call to this function. All list-data will be allocated by
|
||||||
the function itself. You must call \fIcurl_formfree\fP after the form post has
|
the function itself. You must call \fIcurl_formfree\fP after the form post has
|
||||||
been done to free the resources again.
|
been done to free the resources again.
|
||||||
|
|
||||||
This function will copy all input data except the data pointed to by
|
This function will copy all input data except the data pointed to by the
|
||||||
the arguments after CURLFORM_PTRNAME and CURLFORM_PTRCONTENTS and keep
|
arguments after \fBCURLFORM_PTRNAME\fP and \fBCURLFORM_PTRCONTENTS\fP and keep
|
||||||
its own version of it allocated until you call \fIcurl_formfree\fP. When
|
its own version of it allocated until you call \fIcurl_formfree\fP. When
|
||||||
you've passed the pointer to \fIcurl_easy_setopt\fP, you must not free
|
you've passed the pointer to \fIcurl_easy_setopt\fP, you must not free the
|
||||||
the list until after you've called \fIcurl_easy_cleanup\fP for the
|
list until after you've called \fIcurl_easy_cleanup\fP for the curl handle. If
|
||||||
curl handle. If you provide a pointer as an arguments after
|
you provide a pointer as an arguments after \fBCURLFORM_PTRNAME\fP or
|
||||||
CURLFORM_PTRNAME or CURLFORM_PTRCONTENTS you must ensure that the pointer
|
\fBCURLFORM_PTRCONTENTS\fP you must ensure that the pointer stays valid until
|
||||||
stays valid until you call \fIcurl_form_free\fP and \fIcurl_easy_cleanup\fP.
|
you call \fIcurl_form_free\fP and \fIcurl_easy_cleanup\fP.
|
||||||
|
|
||||||
See example below.
|
See example below.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
@@ -74,6 +87,9 @@ Returns non-zero if an error occurs.
|
|||||||
char buffer[] = "test buffer";
|
char buffer[] = "test buffer";
|
||||||
char htmlbuffer[] = "<HTML>test buffer</HTML>";
|
char htmlbuffer[] = "<HTML>test buffer</HTML>";
|
||||||
long htmlbufferlength = strlen(htmlbuffer);
|
long htmlbufferlength = strlen(htmlbuffer);
|
||||||
|
struct curl_forms forms[3];
|
||||||
|
char file1[] = "my-face.jpg";
|
||||||
|
char file2[] = "your-face.jpg";
|
||||||
/* add null character into htmlbuffer, to demonstrate that
|
/* add null character into htmlbuffer, to demonstrate that
|
||||||
transfers of buffers containing null characters actually work
|
transfers of buffers containing null characters actually work
|
||||||
*/
|
*/
|
||||||
@@ -82,40 +98,61 @@ Returns non-zero if an error occurs.
|
|||||||
/* Add simple name/content section */
|
/* Add simple name/content section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
|
||||||
CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
|
CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
|
||||||
|
|
||||||
/* Add simple name/content/contenttype section */
|
/* Add simple name/content/contenttype section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "htmlcode",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "htmlcode",
|
||||||
CURLFORM_COPYCONTENTS, "<HTML></HTML>",
|
CURLFORM_COPYCONTENTS, "<HTML></HTML>",
|
||||||
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
|
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
|
||||||
|
|
||||||
/* Add name/ptrcontent section */
|
/* Add name/ptrcontent section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name_for_ptrcontent",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "name_for_ptrcontent",
|
||||||
CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
|
CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
|
||||||
|
|
||||||
/* Add ptrname/ptrcontent section */
|
/* Add ptrname/ptrcontent section */
|
||||||
curl_formadd(&post, &last, CURLFORM_PTRNAME, namebuffer,
|
curl_formadd(&post, &last, CURLFORM_PTRNAME, namebuffer,
|
||||||
CURLFORM_PTRCONTENTS, buffer, CURLFORM_NAMELENGTH,
|
CURLFORM_PTRCONTENTS, buffer, CURLFORM_NAMELENGTH,
|
||||||
namelength, CURLFORM_END);
|
namelength, CURLFORM_END);
|
||||||
|
|
||||||
/* Add name/ptrcontent/contenttype section */
|
/* Add name/ptrcontent/contenttype section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "html_code_with_hole",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "html_code_with_hole",
|
||||||
CURLFORM_PTRCONTENTS, htmlbuffer,
|
CURLFORM_PTRCONTENTS, htmlbuffer,
|
||||||
CURLFORM_CONTENTSLENGTH, htmlbufferlength,
|
CURLFORM_CONTENTSLENGTH, htmlbufferlength,
|
||||||
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
|
CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
|
||||||
|
|
||||||
/* Add simple file section */
|
/* Add simple file section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
|
||||||
CURLFORM_FILE, "my-face.jpg", CURLFORM_END);
|
CURLFORM_FILE, "my-face.jpg", CURLFORM_END);
|
||||||
|
|
||||||
/* Add file/contenttype section */
|
/* Add file/contenttype section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
|
||||||
CURLFORM_FILE, "my-face.jpg",
|
CURLFORM_FILE, "my-face.jpg",
|
||||||
CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
|
CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
|
||||||
|
|
||||||
/* Add two file section */
|
/* Add two file section */
|
||||||
curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
|
||||||
CURLFORM_FILE, "my-face.jpg",
|
CURLFORM_FILE, "my-face.jpg",
|
||||||
CURLFORM_FILE, "your-face.jpg", CURLFORM_END);
|
CURLFORM_FILE, "your-face.jpg", CURLFORM_END);
|
||||||
|
|
||||||
|
/* Add two file section using CURLFORM_ARRAY */
|
||||||
|
forms[0].option = CURLFORM_FILE;
|
||||||
|
forms[0].value = file1;
|
||||||
|
forms[1].option = CURLFORM_FILE;
|
||||||
|
forms[1].value = file2;
|
||||||
|
forms[2].option = CURLFORM_END;
|
||||||
|
|
||||||
|
/* no option needed for the end marker */
|
||||||
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
|
||||||
|
CURLFORM_ARRAY, forms, CURLFORM_END);
|
||||||
|
/* Add the content of a file as a normal post text value */
|
||||||
|
curl_formadd(&post, &last, CURLFORM_COPYNAME, "filecontent",
|
||||||
|
CURLFORM_FILECONTENT, ".bashrc", CURLFORM_END);
|
||||||
/* Set the form info */
|
/* Set the form info */
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR curl_easy_setopt "(3), "
|
.BR curl_easy_setopt "(3), "
|
||||||
.BR curl_formparse "(3) [deprecated], "
|
.BR curl_formparse "(3) [deprecated], "
|
||||||
.BR curl_formfree "(3)
|
.BR curl_formfree "(3)"
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Surely there are some, you tell me!
|
Surely there are some, you tell me!
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -154,6 +154,7 @@ typedef enum {
|
|||||||
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 - removed after 7.7.3 */
|
||||||
CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */
|
CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */
|
||||||
|
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
|
||||||
|
|
||||||
CURL_LAST /* never use! */
|
CURL_LAST /* never use! */
|
||||||
} CURLcode;
|
} CURLcode;
|
||||||
@@ -460,10 +461,26 @@ typedef enum {
|
|||||||
|
|
||||||
/* Specify which SSL ciphers to use */
|
/* Specify which SSL ciphers to use */
|
||||||
CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
|
CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
|
||||||
|
|
||||||
|
/* Specify which HTTP version to use! This must be set to one of the
|
||||||
|
CURL_HTTP_VERSION* enums set below. */
|
||||||
|
CINIT(HTTP_VERSION, LONG, 84),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unusued */
|
CURLOPT_LASTENTRY /* the last unusued */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
|
||||||
|
enum {
|
||||||
|
CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
|
||||||
|
like the library to choose the best possible
|
||||||
|
for us! */
|
||||||
|
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
|
||||||
|
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
|
||||||
|
|
||||||
|
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TIMECOND_NONE,
|
TIMECOND_NONE,
|
||||||
|
|
||||||
@@ -472,7 +489,7 @@ typedef enum {
|
|||||||
TIMECOND_LASTMOD,
|
TIMECOND_LASTMOD,
|
||||||
|
|
||||||
TIMECOND_LAST
|
TIMECOND_LAST
|
||||||
} TimeCond;
|
} curl_TimeCond;
|
||||||
|
|
||||||
#ifdef __BEOS__
|
#ifdef __BEOS__
|
||||||
#include <support/SupportDefs.h>
|
#include <support/SupportDefs.h>
|
||||||
@@ -512,13 +529,23 @@ typedef enum {
|
|||||||
CFINIT(COPYCONTENTS),
|
CFINIT(COPYCONTENTS),
|
||||||
CFINIT(PTRCONTENTS),
|
CFINIT(PTRCONTENTS),
|
||||||
CFINIT(CONTENTSLENGTH),
|
CFINIT(CONTENTSLENGTH),
|
||||||
|
CFINIT(FILECONTENT),
|
||||||
|
CFINIT(ARRAY),
|
||||||
|
CFINIT(ARRAY_START), /* below are the options allowed within a array */
|
||||||
CFINIT(FILE),
|
CFINIT(FILE),
|
||||||
CFINIT(CONTENTTYPE),
|
CFINIT(CONTENTTYPE),
|
||||||
CFINIT(END),
|
CFINIT(END),
|
||||||
|
CFINIT(ARRAY_END), /* up are the options allowed within a array */
|
||||||
|
|
||||||
CURLFORM_LASTENTRY /* the last unusued */
|
CURLFORM_LASTENTRY /* the last unusued */
|
||||||
} CURLformoption;
|
} CURLformoption;
|
||||||
|
|
||||||
|
/* structure to be used as parameter for CURLFORM_ARRAY */
|
||||||
|
struct curl_forms {
|
||||||
|
CURLformoption option;
|
||||||
|
const char *value;
|
||||||
|
};
|
||||||
|
|
||||||
/* new external form function */
|
/* new external form function */
|
||||||
int curl_formadd(struct HttpPost **httppost,
|
int curl_formadd(struct HttpPost **httppost,
|
||||||
struct HttpPost **last_post,
|
struct HttpPost **last_post,
|
||||||
@@ -548,8 +575,8 @@ CURLcode curl_global_init(long flags);
|
|||||||
void curl_global_cleanup(void);
|
void curl_global_cleanup(void);
|
||||||
|
|
||||||
/* This is the version number */
|
/* This is the version number */
|
||||||
#define LIBCURL_VERSION "7.9"
|
#define LIBCURL_VERSION "7.9.1"
|
||||||
#define LIBCURL_VERSION_NUM 0x070900
|
#define LIBCURL_VERSION_NUM 0x070901
|
||||||
|
|
||||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||||
struct curl_slist {
|
struct curl_slist {
|
||||||
|
@@ -1,134 +0,0 @@
|
|||||||
/**
|
|
||||||
* The curl class is a JNI wrapper for libcurl. Please bear with me, I'm no
|
|
||||||
* true java dude (yet). Improve what you think is bad and send me the
|
|
||||||
* updates!
|
|
||||||
* daniel@haxx.se
|
|
||||||
*
|
|
||||||
* This is meant as a raw, crude and low-level interface to libcurl. If you
|
|
||||||
* want fancy stuff, build upon this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CurlGlue
|
|
||||||
{
|
|
||||||
// start of imported generated list, make a new list with
|
|
||||||
// define2java.pl on demand
|
|
||||||
public static final int CURLOPT_NOTHING = 0;
|
|
||||||
public static final int CURLOPT_FILE = 10001;
|
|
||||||
public static final int CURLOPT_URL = 10002;
|
|
||||||
public static final int CURLOPT_PORT = 3;
|
|
||||||
public static final int CURLOPT_PROXY = 10004;
|
|
||||||
public static final int CURLOPT_USERPWD = 10005;
|
|
||||||
public static final int CURLOPT_PROXYUSERPWD = 10006;
|
|
||||||
public static final int CURLOPT_RANGE = 10007;
|
|
||||||
public static final int CURLOPT_INFILE = 10009;
|
|
||||||
public static final int CURLOPT_ERRORBUFFER = 10010;
|
|
||||||
public static final int CURLOPT_WRITEFUNCTION = 20011;
|
|
||||||
public static final int CURLOPT_READFUNCTION = 20012;
|
|
||||||
public static final int CURLOPT_TIMEOUT = 13;
|
|
||||||
public static final int CURLOPT_INFILESIZE = 14;
|
|
||||||
public static final int CURLOPT_POSTFIELDS = 10015;
|
|
||||||
public static final int CURLOPT_REFERER = 10016;
|
|
||||||
public static final int CURLOPT_FTPPORT = 10017;
|
|
||||||
public static final int CURLOPT_USERAGENT = 10018;
|
|
||||||
public static final int CURLOPT_LOW_SPEED_LIMIT = 19;
|
|
||||||
public static final int CURLOPT_LOW_SPEED_TIME = 20;
|
|
||||||
public static final int CURLOPT_RESUME_FROM = 21;
|
|
||||||
public static final int CURLOPT_COOKIE = 10022;
|
|
||||||
public static final int CURLOPT_HTTPHEADER = 10023;
|
|
||||||
public static final int CURLOPT_HTTPPOST = 10024;
|
|
||||||
public static final int CURLOPT_SSLCERT = 10025;
|
|
||||||
public static final int CURLOPT_SSLCERTPASSWD = 10026;
|
|
||||||
public static final int CURLOPT_CRLF = 27;
|
|
||||||
public static final int CURLOPT_QUOTE = 10028;
|
|
||||||
public static final int CURLOPT_WRITEHEADER = 10029;
|
|
||||||
public static final int CURLOPT_COOKIEFILE = 10031;
|
|
||||||
public static final int CURLOPT_SSLVERSION = 32;
|
|
||||||
public static final int CURLOPT_TIMECONDITION = 33;
|
|
||||||
public static final int CURLOPT_TIMEVALUE = 34;
|
|
||||||
public static final int CURLOPT_HTTPREQUEST = 10035;
|
|
||||||
public static final int CURLOPT_CUSTOMREQUEST = 10036;
|
|
||||||
public static final int CURLOPT_STDERR = 10037;
|
|
||||||
public static final int CURLOPT_POSTQUOTE = 10039;
|
|
||||||
public static final int CURLOPT_WRITEINFO = 10040;
|
|
||||||
public static final int CURLOPT_VERBOSE = 41;
|
|
||||||
public static final int CURLOPT_HEADER = 42;
|
|
||||||
public static final int CURLOPT_NOPROGRESS = 43;
|
|
||||||
public static final int CURLOPT_NOBODY = 44;
|
|
||||||
public static final int CURLOPT_FAILONERROR = 45;
|
|
||||||
public static final int CURLOPT_UPLOAD = 46;
|
|
||||||
public static final int CURLOPT_POST = 47;
|
|
||||||
public static final int CURLOPT_FTPLISTONLY = 48;
|
|
||||||
public static final int CURLOPT_FTPAPPEND = 50;
|
|
||||||
public static final int CURLOPT_NETRC = 51;
|
|
||||||
public static final int CURLOPT_FOLLOWLOCATION = 52;
|
|
||||||
public static final int CURLOPT_FTPASCII = 53;
|
|
||||||
public static final int CURLOPT_TRANSFERTEXT = 53;
|
|
||||||
public static final int CURLOPT_PUT = 54;
|
|
||||||
public static final int CURLOPT_MUTE = 55;
|
|
||||||
public static final int CURLOPT_PROGRESSFUNCTION = 20056;
|
|
||||||
public static final int CURLOPT_PROGRESSDATA = 10057;
|
|
||||||
public static final int CURLOPT_AUTOREFERER = 58;
|
|
||||||
public static final int CURLOPT_PROXYPORT = 59;
|
|
||||||
public static final int CURLOPT_POSTFIELDSIZE = 60;
|
|
||||||
public static final int CURLOPT_HTTPPROXYTUNNEL = 61;
|
|
||||||
public static final int CURLOPT_INTERFACE = 10062;
|
|
||||||
public static final int CURLOPT_KRB4LEVEL = 10063;
|
|
||||||
public static final int CURLOPT_SSL_VERIFYPEER = 64;
|
|
||||||
public static final int CURLOPT_CAINFO = 10065;
|
|
||||||
public static final int CURLOPT_PASSWDFUNCTION = 20066;
|
|
||||||
public static final int CURLOPT_PASSWDDATA = 10067;
|
|
||||||
public static final int CURLOPT_MAXREDIRS = 68;
|
|
||||||
public static final int CURLOPT_FILETIME = 10069;
|
|
||||||
public static final int CURLOPT_TELNETOPTIONS = 10070;
|
|
||||||
public static final int CURLOPT_MAXCONNECTS = 71;
|
|
||||||
public static final int CURLOPT_CLOSEPOLICY = 72;
|
|
||||||
public static final int CURLOPT_CLOSEFUNCTION = 20073;
|
|
||||||
public static final int CURLOPT_FRESH_CONNECT = 74;
|
|
||||||
public static final int CURLOPT_FORBID_REUSE = 75;
|
|
||||||
public static final int CURLOPT_RANDOM_FILE = 10076;
|
|
||||||
public static final int CURLOPT_EGDSOCKET = 10077;
|
|
||||||
public static final int CURLOPT_CONNECTTIMEOUT = 78;
|
|
||||||
public static final int CURLOPT_HEADERFUNCTION = 20079;
|
|
||||||
// end of generated list
|
|
||||||
|
|
||||||
public CurlGlue() {
|
|
||||||
javacurl_handle = jni_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finalize() {
|
|
||||||
jni_cleanup(javacurl_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int javacurl_handle;
|
|
||||||
|
|
||||||
/* constructor and destructor for the libcurl handle */
|
|
||||||
private native int jni_init();
|
|
||||||
private native void jni_cleanup(int javacurl_handle);
|
|
||||||
private native synchronized int jni_perform(int javacurl_handle);
|
|
||||||
|
|
||||||
// Instead of varargs, we have different functions for each
|
|
||||||
// kind of type setopt() can take
|
|
||||||
private native int jni_setopt(int libcurl, int option, String value);
|
|
||||||
private native int jni_setopt(int libcurl, int option, int value);
|
|
||||||
private native int jni_setopt(int libcurl, int option, CurlWrite value);
|
|
||||||
|
|
||||||
public native int getinfo();
|
|
||||||
|
|
||||||
public int perform() {
|
|
||||||
return jni_perform(javacurl_handle);
|
|
||||||
}
|
|
||||||
public int setopt(int option, int value) {
|
|
||||||
return jni_setopt(javacurl_handle, option, value);
|
|
||||||
}
|
|
||||||
public int setopt(int option, String value) {
|
|
||||||
return jni_setopt(javacurl_handle, option, value);
|
|
||||||
}
|
|
||||||
public int setopt(int option, CurlWrite value) {
|
|
||||||
return jni_setopt(javacurl_handle, option, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
System.loadLibrary("javacurl");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
public interface CurlWrite
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* handleString gets called by libcurl on each chunk of data
|
|
||||||
* we receive from the remote server
|
|
||||||
*/
|
|
||||||
public int handleString(byte s[]);
|
|
||||||
}
|
|
||||||
|
|
@@ -1,8 +0,0 @@
|
|||||||
CurlGlue.java
|
|
||||||
CurlWrite.java
|
|
||||||
define2java.pl
|
|
||||||
javacurl.c
|
|
||||||
Makefile
|
|
||||||
README
|
|
||||||
test.java
|
|
||||||
MANIFEST
|
|
@@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
TARGET = libjavacurl.so
|
|
||||||
|
|
||||||
OBJS = javacurl.o
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -c
|
|
||||||
CPPFLAGS = -I/usr/j2se/include -I/usr/local/include -I/usr/j2se/include/solaris
|
|
||||||
|
|
||||||
# Linux might use -shared -Wl,-soname,libnative.so instead of -G
|
|
||||||
LDFLAGS = -G -lcurl -ldl -L/usr/local/ssl/lib -lssl -lcrypto
|
|
||||||
|
|
||||||
all: CurlGlue.h CurlGlue.class javacurl.o $(TARGET) test.class
|
|
||||||
|
|
||||||
test:
|
|
||||||
java test
|
|
||||||
|
|
||||||
javacurl.o: javacurl.c CurlGlue.h
|
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $<
|
|
||||||
|
|
||||||
CurlGlue.h: CurlGlue.java CurlGlue.class
|
|
||||||
javah CurlGlue
|
|
||||||
touch CurlGlue.h
|
|
||||||
|
|
||||||
test.class: CurlGlue.class javacurl.o
|
|
||||||
javac test.java
|
|
||||||
|
|
||||||
CurlGlue.class: CurlGlue.java
|
|
||||||
javac $<
|
|
||||||
|
|
||||||
$(TARGET): $(OBJS)
|
|
||||||
$(CC) -o $(TARGET) $(LDFLAGS) $(OBJS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f javacurl.o CurlGlue.h CurlGlue.class
|
|
17
java/README
17
java/README
@@ -1,17 +0,0 @@
|
|||||||
_ _ ____ _
|
|
||||||
___| | | | _ \| |
|
|
||||||
/ __| | | | |_) | |
|
|
||||||
| (__| |_| | _ <| |___
|
|
||||||
\___|\___/|_| \_\_____|
|
|
||||||
|
|
||||||
Java Interface
|
|
||||||
|
|
||||||
This is not a complete implementation of a libcurl interface. I've made the
|
|
||||||
core work and it needs additional code to be added to get the rest of the
|
|
||||||
stuff supported.
|
|
||||||
|
|
||||||
The interface is not set yet, bring your suggestions!
|
|
||||||
|
|
||||||
Feel free to grab the source files in here and help out!
|
|
||||||
|
|
||||||
The 'test.java' is the actual program that uses the curl stuff.
|
|
@@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
open(GCC, "gcc -E ../include/curl/curl.h|");
|
|
||||||
|
|
||||||
while(<GCC>) {
|
|
||||||
if($_ =~ /(CURLOPT_(.*)) += (.*)/) {
|
|
||||||
$var= $1;
|
|
||||||
$expr = $3;
|
|
||||||
$f=$3;
|
|
||||||
if($expr =~ / *(\d+) *\+ *(\d+)/) {
|
|
||||||
$expr = $1+$2;
|
|
||||||
}
|
|
||||||
|
|
||||||
# nah, keep the CURL prefix to make them look like other
|
|
||||||
# languages' defines
|
|
||||||
# $var =~ s/^CURL//g;
|
|
||||||
|
|
||||||
print " public static final int $var = $expr;\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(GCC);
|
|
218
java/javacurl.c
218
java/javacurl.c
@@ -1,218 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* _ _ ____ _
|
|
||||||
* Project ___| | | | _ \| |
|
|
||||||
* / __| | | | |_) | |
|
|
||||||
* | (__| |_| | _ <| |___
|
|
||||||
* \___|\___/|_| \_\_____|
|
|
||||||
*
|
|
||||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
||||||
*
|
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
|
||||||
*
|
|
||||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
||||||
* copies of the Software, and permit persons to whom the Software is
|
|
||||||
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
|
||||||
* licenses. You may pick one of these licenses.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include <curl/curl.h> /* libcurl header */
|
|
||||||
#include "CurlGlue.h" /* the JNI-generated glue header file */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a private struct allocated for every 'CurlGlue' object.
|
|
||||||
*/
|
|
||||||
struct javacurl {
|
|
||||||
void *libcurl;
|
|
||||||
void *whatever;
|
|
||||||
struct writecallback {
|
|
||||||
jmethodID mid;
|
|
||||||
JNIEnv *java;
|
|
||||||
jclass cls; /* global reference */
|
|
||||||
jobject object;
|
|
||||||
} write;
|
|
||||||
};
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1init(JNIEnv *java,
|
|
||||||
jobject myself)
|
|
||||||
{
|
|
||||||
void *libhandle;
|
|
||||||
struct javacurl *jcurl=NULL;
|
|
||||||
|
|
||||||
libhandle = curl_easy_init();
|
|
||||||
|
|
||||||
if(libhandle) {
|
|
||||||
jcurl=(struct javacurl *)malloc(sizeof(struct javacurl));
|
|
||||||
if(jcurl) {
|
|
||||||
memset(jcurl, 0, sizeof(struct javacurl));
|
|
||||||
jcurl->libcurl = libhandle;
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
curl_easy_cleanup(libhandle);
|
|
||||||
return (jint)0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (jint) jcurl; /* nasty typecast */
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_CurlGlue_jni_1cleanup(JNIEnv *java,
|
|
||||||
jobject myself,
|
|
||||||
jint jcurl)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct javacurl *curl = (struct javacurl*)jcurl;
|
|
||||||
|
|
||||||
if(curl->write.cls) {
|
|
||||||
/* a global reference we must delete */
|
|
||||||
(*java)->DeleteGlobalRef(java, curl->write.cls);
|
|
||||||
(*java)->DeleteGlobalRef(java, curl->write.object);
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl->libcurl); /* cleanup libcurl stuff */
|
|
||||||
|
|
||||||
free((void *)curl); /* free the struct too */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* setopt() int + string
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILjava_lang_String_2
|
|
||||||
(JNIEnv *java, jobject myself, jint jcurl, jint option, jstring value)
|
|
||||||
{
|
|
||||||
/* get the actual string C-style */
|
|
||||||
const char *str = (*java)->GetStringUTFChars(java, value, 0);
|
|
||||||
|
|
||||||
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
|
|
||||||
|
|
||||||
puts("setopt int + string");
|
|
||||||
|
|
||||||
return (jint)curl_easy_setopt(handle, (CURLoption)option, str);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* setopt() int + int
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__III
|
|
||||||
(JNIEnv *java, jobject myself, jint jcurl, jint option, jint value)
|
|
||||||
{
|
|
||||||
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
|
|
||||||
CURLoption opt = (CURLoption)option;
|
|
||||||
|
|
||||||
puts("setopt int + int");
|
|
||||||
|
|
||||||
switch(opt) {
|
|
||||||
case CURLOPT_FILE:
|
|
||||||
/* silently ignored, we don't need user-specified callback data when
|
|
||||||
we have an object, and besides the CURLOPT_FILE is not exported
|
|
||||||
to the java interface */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (jint)curl_easy_setopt(handle, (CURLoption)option, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int javacurl_write_callback(void *ptr,
|
|
||||||
size_t size,
|
|
||||||
size_t nmemb,
|
|
||||||
FILE *stream)
|
|
||||||
{
|
|
||||||
struct javacurl *curl = (struct javacurl *)stream;
|
|
||||||
size_t realsize = size * nmemb;
|
|
||||||
JNIEnv *java = curl->write.java;
|
|
||||||
jbyteArray jb=NULL;
|
|
||||||
int ret=0;
|
|
||||||
|
|
||||||
fprintf(stderr, "%d bytes data received in callback:\n"
|
|
||||||
"ptr=%p, java=%p cls=%p\n",
|
|
||||||
realsize, curl, java, curl->write.cls);
|
|
||||||
|
|
||||||
jb=(*java)->NewByteArray(java, realsize);
|
|
||||||
(*java)->SetByteArrayRegion(java, jb, 0,
|
|
||||||
realsize, (jbyte *)ptr);
|
|
||||||
|
|
||||||
fprintf(stderr, "created byte-array\n");
|
|
||||||
|
|
||||||
ret = (*java)->CallIntMethod(java,
|
|
||||||
curl->write.object,
|
|
||||||
curl->write.mid,
|
|
||||||
jb);
|
|
||||||
|
|
||||||
fprintf(stderr, "java-method returned %d\n", ret);
|
|
||||||
|
|
||||||
return realsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* setopt() int + object
|
|
||||||
*/
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILCurlWrite_2
|
|
||||||
(JNIEnv *java, jobject myself, jint jcurl, jint option, jobject object)
|
|
||||||
{
|
|
||||||
jclass cls_local = (*java)->GetObjectClass(java, object);
|
|
||||||
jmethodID mid;
|
|
||||||
struct javacurl *curl = (struct javacurl *)jcurl;
|
|
||||||
jclass cls;
|
|
||||||
jobject obj_global;
|
|
||||||
|
|
||||||
switch(option) {
|
|
||||||
case CURLOPT_WRITEFUNCTION:
|
|
||||||
/* this makes a reference that'll be alive until we kill it! */
|
|
||||||
cls = (*java)->NewGlobalRef(java, cls_local);
|
|
||||||
|
|
||||||
printf("setopt int + object, option = %d cls= %p\n",
|
|
||||||
option, cls);
|
|
||||||
|
|
||||||
if(!cls) {
|
|
||||||
puts("couldn't make local reference global");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this is the write callback */
|
|
||||||
mid = (*java)->GetMethodID(java, cls, "handleString", "([B)I");
|
|
||||||
if(!mid) {
|
|
||||||
puts("no callback method found");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj_global = (*java)->NewGlobalRef(java, object);
|
|
||||||
|
|
||||||
curl->write.mid = mid;
|
|
||||||
curl->write.cls = cls;
|
|
||||||
curl->write.object = obj_global;
|
|
||||||
/*curl->write.java = java; stored on perform */
|
|
||||||
|
|
||||||
fprintf(stderr, "setopt write callback and write file pointer %p, java = %p\n",
|
|
||||||
curl, java);
|
|
||||||
|
|
||||||
curl_easy_setopt(curl->libcurl, CURLOPT_WRITEFUNCTION,
|
|
||||||
javacurl_write_callback);
|
|
||||||
curl_easy_setopt(curl->libcurl, CURLOPT_FILE,
|
|
||||||
curl);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_getinfo
|
|
||||||
(JNIEnv *java, jobject value)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1perform
|
|
||||||
(JNIEnv *java, jobject myself, jint jcurl)
|
|
||||||
{
|
|
||||||
struct javacurl *curl=(struct javacurl*)jcurl;
|
|
||||||
curl->write.java = java;
|
|
||||||
return (jint)curl_easy_perform(curl->libcurl);
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
import CurlGlue;
|
|
||||||
import CurlWrite;
|
|
||||||
|
|
||||||
class test implements CurlWrite {
|
|
||||||
public int handleString(byte s[])
|
|
||||||
{
|
|
||||||
/* output everything */
|
|
||||||
System.out.println("IIIIIIIIIII -------------- OOOOOOOOOOOOOOOOOOO");
|
|
||||||
try {
|
|
||||||
System.out.write(s);
|
|
||||||
}
|
|
||||||
catch (java.io.IOException moo) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
CurlGlue cg = new CurlGlue();
|
|
||||||
test cw = new test();
|
|
||||||
cg.setopt(CurlGlue.CURLOPT_URL, "http://www.contactor.se/");
|
|
||||||
cg.setopt(CurlGlue.CURLOPT_WRITEFUNCTION, cw);
|
|
||||||
cg.perform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -16,7 +16,7 @@ lib_LTLIBRARIES = libcurl.la
|
|||||||
INCLUDES = -I$(top_srcdir)/include
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
|
|
||||||
|
|
||||||
libcurl_la_LDFLAGS = -version-info 2:2:0
|
libcurl_la_LDFLAGS = -no-undefined -version-info 2:2: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
|
||||||
# 1.
|
# 1.
|
||||||
@@ -59,7 +59,7 @@ escape.c mprintf.c telnet.c \
|
|||||||
escape.h getpass.c netrc.c telnet.h \
|
escape.h getpass.c netrc.c telnet.h \
|
||||||
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
|
getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
|
||||||
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
||||||
http_chunks.c http_chunks.h strtok.c strtok.h
|
http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h
|
||||||
|
|
||||||
noinst_HEADERS = setup.h transfer.h
|
noinst_HEADERS = setup.h transfer.h
|
||||||
|
|
||||||
|
@@ -58,7 +58,8 @@ SOURCES = \
|
|||||||
version.c \
|
version.c \
|
||||||
easy.c \
|
easy.c \
|
||||||
strequal.c \
|
strequal.c \
|
||||||
strtok.c
|
strtok.c \
|
||||||
|
connect.c
|
||||||
|
|
||||||
OBJECTS = $(SOURCES:.c=.obj)
|
OBJECTS = $(SOURCES:.c=.obj)
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
#############################################################
|
#############################################################
|
||||||
# $Id$
|
|
||||||
#
|
#
|
||||||
## Makefile for building libcurl.a with MingW32 (GCC-2.95) and
|
## Makefile for building libcurl.a with MingW32 (GCC-2.95) and
|
||||||
## optionally OpenSSL (0.9.6)
|
## optionally OpenSSL (0.9.6)
|
||||||
@@ -12,7 +11,7 @@ CC = gcc
|
|||||||
AR = ar
|
AR = ar
|
||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
STRIP = strip -g
|
STRIP = strip -g
|
||||||
OPENSSL_PATH = ../../openssl-0.9.6
|
OPENSSL_PATH = ../../openssl-0.9.6b
|
||||||
|
|
||||||
########################################################
|
########################################################
|
||||||
## Nothing more to do below this line!
|
## Nothing more to do below this line!
|
||||||
@@ -36,14 +35,14 @@ libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
|
|||||||
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \
|
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \
|
||||||
telnet.h getinfo.c strequal.c strequal.h easy.c security.h \
|
telnet.h getinfo.c strequal.c strequal.h easy.c security.h \
|
||||||
security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \
|
security.c krb4.h krb4.c memdebug.h memdebug.c inet_ntoa_r.h http_chunks.h http_chunks.c \
|
||||||
strtok.c
|
strtok.c connect.c
|
||||||
|
|
||||||
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
|
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
|
||||||
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
|
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
|
||||||
speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \
|
speedcheck.o getdate.o transfer.o ldap.o ssluse.o version.o \
|
||||||
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
|
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
|
||||||
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
|
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
|
||||||
strtok.o
|
strtok.o connect.o
|
||||||
|
|
||||||
LIBRARIES = $(libcurl_a_LIBRARIES)
|
LIBRARIES = $(libcurl_a_LIBRARIES)
|
||||||
SOURCES = $(libcurl_a_SOURCES)
|
SOURCES = $(libcurl_a_SOURCES)
|
||||||
@@ -62,7 +61,7 @@ libcurl.a: $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
|
|||||||
|
|
||||||
libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o
|
libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o
|
||||||
-@erase $@
|
-@erase $@
|
||||||
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32
|
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32 -lws2_32
|
||||||
$(STRIP) $@
|
$(STRIP) $@
|
||||||
|
|
||||||
# remove the last line above to keep debug info
|
# remove the last line above to keep debug info
|
||||||
|
@@ -62,7 +62,8 @@ RELEASE_OBJS= \
|
|||||||
versionr.obj \
|
versionr.obj \
|
||||||
easyr.obj \
|
easyr.obj \
|
||||||
strequalr.obj \
|
strequalr.obj \
|
||||||
strtokr.obj
|
strtokr.obj \
|
||||||
|
connectr.obj
|
||||||
|
|
||||||
DEBUG_OBJS= \
|
DEBUG_OBJS= \
|
||||||
base64d.obj \
|
base64d.obj \
|
||||||
@@ -94,7 +95,8 @@ DEBUG_OBJS= \
|
|||||||
versiond.obj \
|
versiond.obj \
|
||||||
easyd.obj \
|
easyd.obj \
|
||||||
strequald.obj \
|
strequald.obj \
|
||||||
strtokd.obj
|
strtokd.obj \
|
||||||
|
connectd.obj
|
||||||
|
|
||||||
RELEASE_SSL_OBJS= \
|
RELEASE_SSL_OBJS= \
|
||||||
base64rs.obj \
|
base64rs.obj \
|
||||||
@@ -126,7 +128,8 @@ RELEASE_SSL_OBJS= \
|
|||||||
versionrs.obj \
|
versionrs.obj \
|
||||||
easyrs.obj \
|
easyrs.obj \
|
||||||
strequalrs.obj \
|
strequalrs.obj \
|
||||||
strtokrs.obj
|
strtokrs.obj \
|
||||||
|
connectrs.obj
|
||||||
|
|
||||||
LINK_OBJS= \
|
LINK_OBJS= \
|
||||||
base64.obj \
|
base64.obj \
|
||||||
@@ -158,7 +161,8 @@ LINK_OBJS= \
|
|||||||
version.obj \
|
version.obj \
|
||||||
easy.obj \
|
easy.obj \
|
||||||
strequal.obj \
|
strequal.obj \
|
||||||
strtok.obj
|
strtok.obj \
|
||||||
|
connect.obj
|
||||||
|
|
||||||
all : release
|
all : release
|
||||||
|
|
||||||
@@ -232,6 +236,8 @@ strequalr.obj: strequal.c
|
|||||||
$(CCR) $(CFLAGS) strequal.c
|
$(CCR) $(CFLAGS) strequal.c
|
||||||
strtokr.obj:strtok.c
|
strtokr.obj:strtok.c
|
||||||
$(CCR) $(CFLAGS) strtok.c
|
$(CCR) $(CFLAGS) strtok.c
|
||||||
|
connectr.obj:connect.c
|
||||||
|
$(CCR) $(CFLAGS) connect.c
|
||||||
|
|
||||||
## Debug
|
## Debug
|
||||||
base64d.obj: base64.c
|
base64d.obj: base64.c
|
||||||
@@ -294,6 +300,8 @@ strequald.obj: strequal.c
|
|||||||
$(CCD) $(CFLAGS) strequal.c
|
$(CCD) $(CFLAGS) strequal.c
|
||||||
strtokd.obj:strtok.c
|
strtokd.obj:strtok.c
|
||||||
$(CCD) $(CFLAGS) strtok.c
|
$(CCD) $(CFLAGS) strtok.c
|
||||||
|
connectd.obj:connect.c
|
||||||
|
$(CCR) $(CFLAGS) connect.c
|
||||||
|
|
||||||
## Release SSL
|
## Release SSL
|
||||||
base64rs.obj: base64.c
|
base64rs.obj: base64.c
|
||||||
@@ -356,7 +364,8 @@ strequalrs.obj: strequal.c
|
|||||||
$(CCRS) $(CFLAGS) strequal.c
|
$(CCRS) $(CFLAGS) strequal.c
|
||||||
strtokrs.obj:strtok.c
|
strtokrs.obj:strtok.c
|
||||||
$(CCRS) $(CFLAGS) strtok.c
|
$(CCRS) $(CFLAGS) strtok.c
|
||||||
|
connectrs.obj:connect.c
|
||||||
|
$(CCR) $(CFLAGS) connect.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-@erase *.obj
|
-@erase *.obj
|
||||||
|
@@ -265,6 +265,6 @@ void *suck(int *lenptr) {
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
562
lib/connect.c
Normal file
562
lib/connect.c
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
/* headers for non-win32 */
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define HAVE_IOCTLSOCKET
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock.h>
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "if2ip.h"
|
||||||
|
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
#include "memdebug.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
int geterrno(void)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return (int)GetLastError();
|
||||||
|
#else
|
||||||
|
return errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Curl_nonblock
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Set the socket to either blocking or non-blocking mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Curl_nonblock(int socket, /* operate on this */
|
||||||
|
int nonblock /* TRUE or FALSE */)
|
||||||
|
{
|
||||||
|
#undef SETBLOCK
|
||||||
|
#ifdef HAVE_O_NONBLOCK
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = fcntl(socket, F_GETFL, 0);
|
||||||
|
if (TRUE == nonblock)
|
||||||
|
return fcntl(socket, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
else
|
||||||
|
return fcntl(socket, F_SETFL, flags & (~O_NONBLOCK));
|
||||||
|
#define SETBLOCK 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FIONBIO
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = nonblock;
|
||||||
|
return ioctl(socket, FIONBIO, &flags);
|
||||||
|
#define SETBLOCK 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IOCTLSOCKET
|
||||||
|
int flags;
|
||||||
|
flags = nonblock;
|
||||||
|
return ioctlsocket(socket, FIONBIO, &flags);
|
||||||
|
#define SETBLOCK 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IOCTLSOCKET_CASE
|
||||||
|
return IoctlSocket(socket, FIONBIO, (long)nonblock);
|
||||||
|
#define SETBLOCK 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DISABLED_NONBLOCKING
|
||||||
|
return 0; /* returns success */
|
||||||
|
#define SETBLOCK 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SETBLOCK
|
||||||
|
#error "no non-blocking method was found/used/set"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 on fine connect, -1 on error and 1 on timeout.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int waitconnect(int sockfd, /* socket */
|
||||||
|
int timeout_msec)
|
||||||
|
{
|
||||||
|
fd_set fd;
|
||||||
|
fd_set errfd;
|
||||||
|
struct timeval interval;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* now select() until we get connect or timeout */
|
||||||
|
FD_ZERO(&fd);
|
||||||
|
FD_SET(sockfd, &fd);
|
||||||
|
|
||||||
|
FD_ZERO(&errfd);
|
||||||
|
FD_SET(sockfd, &errfd);
|
||||||
|
|
||||||
|
interval.tv_sec = timeout_msec/1000;
|
||||||
|
timeout_msec -= interval.tv_sec*1000;
|
||||||
|
|
||||||
|
interval.tv_usec = timeout_msec*1000;
|
||||||
|
|
||||||
|
rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
|
||||||
|
if(-1 == rc)
|
||||||
|
/* error, no connect here, try next */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
else if(0 == rc)
|
||||||
|
/* timeout, no connect today */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(FD_ISSET(sockfd, &errfd)) {
|
||||||
|
/* error condition caught */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have a connect! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ENABLE_IPV6
|
||||||
|
static CURLcode bindlocal(struct connectdata *conn,
|
||||||
|
int sockfd)
|
||||||
|
{
|
||||||
|
#if !defined(WIN32)||defined(__CYGWIN32__)
|
||||||
|
/* We don't generally like checking for OS-versions, we should make this
|
||||||
|
HAVE_XXXX based, although at the moment I don't have a decent test for
|
||||||
|
this! */
|
||||||
|
|
||||||
|
#ifdef HAVE_INET_NTOA
|
||||||
|
|
||||||
|
#ifndef INADDR_NONE
|
||||||
|
#define INADDR_NONE (unsigned long) ~0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Select device to bind socket to
|
||||||
|
*************************************************************/
|
||||||
|
if (strlen(data->set.device)<255) {
|
||||||
|
struct sockaddr_in sa;
|
||||||
|
struct hostent *h=NULL;
|
||||||
|
char *hostdataptr=NULL;
|
||||||
|
size_t size;
|
||||||
|
char myhost[256] = "";
|
||||||
|
unsigned long in;
|
||||||
|
|
||||||
|
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
|
||||||
|
h = Curl_getaddrinfo(data, myhost, 0, &hostdataptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(strlen(data->set.device)>1) {
|
||||||
|
h = Curl_getaddrinfo(data, data->set.device, 0, &hostdataptr);
|
||||||
|
}
|
||||||
|
if(h) {
|
||||||
|
/* we know data->set.device is shorter than the myhost array */
|
||||||
|
strcpy(myhost, data->set.device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! *myhost) {
|
||||||
|
/* need to fix this
|
||||||
|
h=Curl_gethost(data,
|
||||||
|
getmyhost(*myhost,sizeof(myhost)),
|
||||||
|
hostent_buf,
|
||||||
|
sizeof(hostent_buf));
|
||||||
|
*/
|
||||||
|
if(hostdataptr)
|
||||||
|
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
infof(data, "We bind local end to %s\n", myhost);
|
||||||
|
|
||||||
|
if ( (in=inet_addr(myhost)) != INADDR_NONE ) {
|
||||||
|
|
||||||
|
if ( h ) {
|
||||||
|
memset((char *)&sa, 0, sizeof(sa));
|
||||||
|
memcpy((char *)&sa.sin_addr,
|
||||||
|
h->h_addr,
|
||||||
|
h->h_length);
|
||||||
|
sa.sin_family = AF_INET;
|
||||||
|
sa.sin_addr.s_addr = in;
|
||||||
|
sa.sin_port = 0; /* get any port */
|
||||||
|
|
||||||
|
if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) {
|
||||||
|
/* we succeeded to bind */
|
||||||
|
struct sockaddr_in add;
|
||||||
|
|
||||||
|
size = sizeof(add);
|
||||||
|
if(getsockname(sockfd, (struct sockaddr *) &add,
|
||||||
|
(socklen_t *)&size)<0) {
|
||||||
|
failf(data, "getsockname() failed");
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(errno) {
|
||||||
|
case EBADF:
|
||||||
|
failf(data, "Invalid descriptor: %d", errno);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
failf(data, "Invalid request: %d", errno);
|
||||||
|
break;
|
||||||
|
case EACCES:
|
||||||
|
failf(data, "Address is protected, user not superuser: %d", errno);
|
||||||
|
break;
|
||||||
|
case ENOTSOCK:
|
||||||
|
failf(data,
|
||||||
|
"Argument is a descriptor for a file, not a socket: %d",
|
||||||
|
errno);
|
||||||
|
break;
|
||||||
|
case EFAULT:
|
||||||
|
failf(data, "Inaccessable memory error: %d", errno);
|
||||||
|
break;
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
failf(data, "Address too long: %d", errno);
|
||||||
|
break;
|
||||||
|
case ENOMEM:
|
||||||
|
failf(data, "Insufficient kernel memory was available: %d", errno);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
failf(data, "errno %d\n", errno);
|
||||||
|
break;
|
||||||
|
} /* end of switch(errno) */
|
||||||
|
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
} /* end of else */
|
||||||
|
|
||||||
|
} /* end of if h */
|
||||||
|
else {
|
||||||
|
failf(data,"could't find my own IP address (%s)", myhost);
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
} /* end of inet_addr */
|
||||||
|
|
||||||
|
else {
|
||||||
|
failf(data, "could't find my own IP address (%s)", myhost);
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hostdataptr)
|
||||||
|
free(hostdataptr); /* allocated by Curl_getaddrinfo() */
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
|
||||||
|
} /* end of device selection support */
|
||||||
|
#endif /* end of HAVE_INET_NTOA */
|
||||||
|
#endif /* end of not WIN32 */
|
||||||
|
|
||||||
|
return CURLE_HTTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
#else /* end of ipv4-specific section */
|
||||||
|
|
||||||
|
/* we only use socketerror() on IPv6-enabled machines */
|
||||||
|
static
|
||||||
|
int socketerror(int sockfd)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
socklen_t errSize = sizeof(err);
|
||||||
|
|
||||||
|
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||||
|
(void *)&err, &errSize))
|
||||||
|
err = geterrno();
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCP connect to the given host with timeout, proxy or remote doesn't matter.
|
||||||
|
* There might be more than one IP address to try out. Fill in the passed
|
||||||
|
* pointer with the connected socket.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||||
|
Curl_addrinfo *remotehost, /* use one in here */
|
||||||
|
int port, /* connect to this */
|
||||||
|
int *sockconn, /* the connected socket */
|
||||||
|
Curl_ipconnect **addr) /* the one we used */
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
int rc;
|
||||||
|
int sockfd=-1;
|
||||||
|
int aliasindex=0;
|
||||||
|
|
||||||
|
struct timeval after;
|
||||||
|
struct timeval before = Curl_tvnow();
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Figure out what maximum time we have left
|
||||||
|
*************************************************************/
|
||||||
|
long timeout_ms=300000; /* milliseconds, default to five minutes */
|
||||||
|
if(data->set.timeout || data->set.connecttimeout) {
|
||||||
|
double has_passed;
|
||||||
|
|
||||||
|
/* Evaluate in milliseconds how much time that has passed */
|
||||||
|
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get the most strict timeout of the ones converted to milliseconds */
|
||||||
|
if(data->set.timeout &&
|
||||||
|
(data->set.timeout>data->set.connecttimeout))
|
||||||
|
timeout_ms = data->set.timeout*1000;
|
||||||
|
else
|
||||||
|
timeout_ms = data->set.connecttimeout*1000;
|
||||||
|
|
||||||
|
/* subtract the passed time */
|
||||||
|
timeout_ms -= (long)has_passed;
|
||||||
|
|
||||||
|
if(timeout_ms < 0)
|
||||||
|
/* a precaution, no need to continue if time already is up */
|
||||||
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
/*
|
||||||
|
* Connecting with IPv6 support is so much easier and cleanly done
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
struct addrinfo *ai;
|
||||||
|
port =0; /* prevent compiler warning */
|
||||||
|
|
||||||
|
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
|
||||||
|
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
|
if (sockfd < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* set socket non-blocking */
|
||||||
|
Curl_nonblock(sockfd, TRUE);
|
||||||
|
|
||||||
|
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
|
||||||
|
|
||||||
|
if(-1 == rc) {
|
||||||
|
int error=geterrno();
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case EINPROGRESS:
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
|
||||||
|
/* On some platforms EAGAIN and EWOULDBLOCK are the
|
||||||
|
* same value, and on others they are different, hence
|
||||||
|
* the odd #if
|
||||||
|
*/
|
||||||
|
case EAGAIN:
|
||||||
|
#endif
|
||||||
|
case EINTR:
|
||||||
|
|
||||||
|
/* asynchronous connect, wait for connect or timeout */
|
||||||
|
rc = waitconnect(sockfd, timeout_ms);
|
||||||
|
break;
|
||||||
|
case ECONNREFUSED: /* no one listening */
|
||||||
|
default:
|
||||||
|
/* unknown error, fallthrough and try another address! */
|
||||||
|
failf(data, "Failed to connect");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(0 == rc) {
|
||||||
|
/* we might be connected, if the socket says it is OK! Ask it! */
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = socketerror(sockfd);
|
||||||
|
if ((0 == err) || (EISCONN == err)) {
|
||||||
|
/* we are connected, awesome! */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* we are _not_ connected, it was a false alert, continue please */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* connect failed or timed out */
|
||||||
|
sclose(sockfd);
|
||||||
|
sockfd = -1;
|
||||||
|
|
||||||
|
/* get a new timeout for next attempt */
|
||||||
|
after = Curl_tvnow();
|
||||||
|
timeout_ms -= Curl_tvdiff(after, before);
|
||||||
|
if(timeout_ms < 0) {
|
||||||
|
failf(data, "connect() timed out!");
|
||||||
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
|
before = after;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sockfd < 0) {
|
||||||
|
failf(data, "connect() failed");
|
||||||
|
return CURLE_COULDNT_CONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now disable the non-blocking mode again */
|
||||||
|
Curl_nonblock(sockfd, FALSE);
|
||||||
|
|
||||||
|
if(addr)
|
||||||
|
*addr = ai; /* the address we ended up connected to */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Connecting with IPv4-only support
|
||||||
|
*/
|
||||||
|
if(!remotehost->h_addr_list[0]) {
|
||||||
|
/* If there is no addresses in the address list, then we return
|
||||||
|
error right away */
|
||||||
|
failf(data, "no address available");
|
||||||
|
return CURLE_COULDNT_CONNECT;
|
||||||
|
}
|
||||||
|
/* create an IPv4 TCP socket */
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(-1 == sockfd) {
|
||||||
|
failf(data, "couldn't create socket");
|
||||||
|
return CURLE_COULDNT_CONNECT; /* big time error */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conn->data->set.device) {
|
||||||
|
/* user selected to bind the outgoing socket to a specified "device"
|
||||||
|
before doing connect */
|
||||||
|
CURLcode res = bindlocal(conn, sockfd);
|
||||||
|
if(res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert socket to non-blocking type */
|
||||||
|
Curl_nonblock(sockfd, TRUE);
|
||||||
|
|
||||||
|
/* This is the loop that attempts to connect to all IP-addresses we
|
||||||
|
know for the given host. One by one. */
|
||||||
|
for(rc=-1, aliasindex=0;
|
||||||
|
rc && (struct in_addr *)remotehost->h_addr_list[aliasindex];
|
||||||
|
aliasindex++) {
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
|
|
||||||
|
/* do this nasty work to do the connect */
|
||||||
|
memset((char *) &serv_addr, '\0', sizeof(serv_addr));
|
||||||
|
memcpy((char *)&(serv_addr.sin_addr),
|
||||||
|
(struct in_addr *)remotehost->h_addr_list[aliasindex],
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
serv_addr.sin_family = remotehost->h_addrtype;
|
||||||
|
serv_addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
rc = connect(sockfd, (struct sockaddr *)&serv_addr,
|
||||||
|
sizeof(serv_addr));
|
||||||
|
|
||||||
|
if(-1 == rc) {
|
||||||
|
int error=geterrno();
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case EINPROGRESS:
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
|
||||||
|
/* On some platforms EAGAIN and EWOULDBLOCK are the
|
||||||
|
* same value, and on others they are different, hence
|
||||||
|
* the odd #if
|
||||||
|
*/
|
||||||
|
case EAGAIN:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* asynchronous connect, wait for connect or timeout */
|
||||||
|
rc = waitconnect(sockfd, timeout_ms);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unknown error, fallthrough and try another address! */
|
||||||
|
failf(data, "Failed to connect to IP number %d", aliasindex+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0 != rc) {
|
||||||
|
/* get a new timeout for next attempt */
|
||||||
|
after = Curl_tvnow();
|
||||||
|
timeout_ms -= Curl_tvdiff(after, before);
|
||||||
|
if(timeout_ms < 0) {
|
||||||
|
failf(data, "Connect timeout on IP number %d", aliasindex+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
before = after;
|
||||||
|
continue; /* try next address */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(0 != rc) {
|
||||||
|
/* no good connect was made */
|
||||||
|
sclose(sockfd);
|
||||||
|
*sockconn = -1;
|
||||||
|
return CURLE_COULDNT_CONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now disable the non-blocking mode again */
|
||||||
|
Curl_nonblock(sockfd, FALSE);
|
||||||
|
|
||||||
|
if(addr)
|
||||||
|
/* this is the address we've connected to */
|
||||||
|
*addr = (struct in_addr *)remotehost->h_addr_list[aliasindex];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* allow NULL-pointers to get passed in */
|
||||||
|
if(sockconn)
|
||||||
|
*sockconn = sockfd; /* the socket descriptor we've connected */
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
35
lib/connect.h
Normal file
35
lib/connect.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __CONNECT_H
|
||||||
|
#define __CONNECT_H
|
||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
||||||
|
* licenses. You may pick one of these licenses.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
int Curl_nonblock(int socket, /* operate on this */
|
||||||
|
int nonblock /* TRUE or FALSE */);
|
||||||
|
|
||||||
|
CURLcode Curl_connecthost(struct connectdata *conn,
|
||||||
|
Curl_addrinfo *host, /* connect to this */
|
||||||
|
long port, /* connect to this port number */
|
||||||
|
int *sockconn, /* not set if error is returned */
|
||||||
|
Curl_ipconnect **addr /* the one we used */
|
||||||
|
); /* index we used */
|
||||||
|
#endif
|
26
lib/cookie.c
26
lib/cookie.c
@@ -104,7 +104,8 @@ Example set of cookies:
|
|||||||
struct Cookie *
|
struct Cookie *
|
||||||
Curl_cookie_add(struct CookieInfo *c,
|
Curl_cookie_add(struct CookieInfo *c,
|
||||||
bool httpheader, /* TRUE if HTTP header-style line */
|
bool httpheader, /* TRUE if HTTP header-style line */
|
||||||
char *lineptr) /* first non-space of the line */
|
char *lineptr, /* first non-space of the line */
|
||||||
|
char *domain) /* default domain */
|
||||||
{
|
{
|
||||||
struct Cookie *clist;
|
struct Cookie *clist;
|
||||||
char what[MAX_COOKIE_LINE];
|
char what[MAX_COOKIE_LINE];
|
||||||
@@ -194,6 +195,10 @@ Curl_cookie_add(struct CookieInfo *c,
|
|||||||
ptr++;
|
ptr++;
|
||||||
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
|
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
|
||||||
} while(semiptr);
|
} while(semiptr);
|
||||||
|
|
||||||
|
if(NULL == co->domain)
|
||||||
|
/* no domain given in the header line, set the default now */
|
||||||
|
co->domain=domain?strdup(domain):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
|
||||||
@@ -369,6 +374,9 @@ Curl_cookie_add(struct CookieInfo *c,
|
|||||||
free(clist->maxage);
|
free(clist->maxage);
|
||||||
|
|
||||||
*clist = *co; /* then store all the new data */
|
*clist = *co; /* then store all the new data */
|
||||||
|
|
||||||
|
free(co); /* free the newly alloced memory */
|
||||||
|
co = clist; /* point to the previous struct instead */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -418,7 +426,7 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
|
|||||||
}
|
}
|
||||||
c->running = FALSE; /* this is not running, this is init */
|
c->running = FALSE; /* this is not running, this is init */
|
||||||
|
|
||||||
if(strequal(file, "-")) {
|
if(file && strequal(file, "-")) {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
fromfile=FALSE;
|
fromfile=FALSE;
|
||||||
}
|
}
|
||||||
@@ -441,7 +449,7 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
|
|||||||
while(*lineptr && isspace((int)*lineptr))
|
while(*lineptr && isspace((int)*lineptr))
|
||||||
lineptr++;
|
lineptr++;
|
||||||
|
|
||||||
Curl_cookie_add(c, headerline, lineptr);
|
Curl_cookie_add(c, headerline, lineptr, NULL);
|
||||||
}
|
}
|
||||||
if(fromfile)
|
if(fromfile)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -619,7 +627,7 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
|
|||||||
if(c) {
|
if(c) {
|
||||||
fputs("# Netscape HTTP Cookie File\n"
|
fputs("# Netscape HTTP Cookie File\n"
|
||||||
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
|
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
|
||||||
"# This is generated by libcurl! Edit on 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;
|
||||||
|
|
||||||
@@ -632,13 +640,13 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
|
|||||||
"%u\t" /* expires */
|
"%u\t" /* expires */
|
||||||
"%s\t" /* name */
|
"%s\t" /* name */
|
||||||
"%s\n", /* value */
|
"%s\n", /* value */
|
||||||
co->domain,
|
co->domain?co->domain:"unknown",
|
||||||
co->field1==2?"TRUE":"FALSE",
|
co->field1==2?"TRUE":"FALSE",
|
||||||
co->path,
|
co->path?co->path:"/",
|
||||||
co->secure?"TRUE":"FALSE",
|
co->secure?"TRUE":"FALSE",
|
||||||
(unsigned int)co->expires,
|
(unsigned int)co->expires,
|
||||||
co->name,
|
co->name,
|
||||||
co->value);
|
co->value?co->value:"");
|
||||||
|
|
||||||
co=co->next;
|
co=co->next;
|
||||||
}
|
}
|
||||||
@@ -681,6 +689,6 @@ int main(int argc, char **argv)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -68,7 +68,13 @@ struct CookieInfo {
|
|||||||
#define MAX_NAME 256
|
#define MAX_NAME 256
|
||||||
#define MAX_NAME_TXT "255"
|
#define MAX_NAME_TXT "255"
|
||||||
|
|
||||||
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool, char *);
|
/*
|
||||||
|
* Add a cookie to the internal list of cookies. The domain argument is only
|
||||||
|
* used if the header boolean is TRUE.
|
||||||
|
*/
|
||||||
|
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line,
|
||||||
|
char *domain);
|
||||||
|
|
||||||
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *);
|
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *);
|
||||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
|
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
|
||||||
void Curl_cookie_freelist(struct Cookie *);
|
void Curl_cookie_freelist(struct Cookie *);
|
||||||
|
@@ -54,7 +54,7 @@ BSC32=bscmake.exe
|
|||||||
# ADD BSC32 /nologo
|
# ADD BSC32 /nologo
|
||||||
LINK32=link.exe
|
LINK32=link.exe
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
# 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 wsock32.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"Release/libcurl.dll"
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
|
|||||||
# ADD BSC32 /nologo
|
# ADD BSC32 /nologo
|
||||||
LINK32=link.exe
|
LINK32=link.exe
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
# 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 wsock32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
# ADD LINK32 kernel32.lib ws2_32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"Debug/libcurl.dll" /pdbtype:sept
|
||||||
# SUBTRACT LINK32 /nodefaultlib
|
# SUBTRACT LINK32 /nodefaultlib
|
||||||
|
|
||||||
!ENDIF
|
!ENDIF
|
||||||
@@ -99,6 +99,10 @@ SOURCE=.\base64.c
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\connect.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\cookie.c
|
SOURCE=.\cookie.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -247,6 +251,10 @@ SOURCE=.\base64.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\connect.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\cookie.h
|
SOURCE=.\cookie.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
83
lib/dict.c
83
lib/dict.c
@@ -136,25 +136,25 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
nth = atoi(nthdef);
|
nth = atoi(nthdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_sendf(conn->firstsocket, conn,
|
result = Curl_sendf(conn->firstsocket, conn,
|
||||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
||||||
"MATCH "
|
"MATCH "
|
||||||
"%s " /* database */
|
"%s " /* database */
|
||||||
"%s " /* strategy */
|
"%s " /* strategy */
|
||||||
"%s\n" /* word */
|
"%s\n" /* word */
|
||||||
"QUIT\n",
|
"QUIT\n",
|
||||||
|
|
||||||
database,
|
database,
|
||||||
strategy,
|
strategy,
|
||||||
word
|
word
|
||||||
);
|
);
|
||||||
|
if(result)
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
failf(data, "Failed sending DICT request");
|
||||||
-1, NULL); /* no upload */
|
else
|
||||||
|
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
||||||
|
-1, NULL); /* no upload */
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
|
else if (strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
|
||||||
strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
|
strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
|
||||||
@@ -186,19 +186,19 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
nth = atoi(nthdef);
|
nth = atoi(nthdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_sendf(conn->firstsocket, conn,
|
result = Curl_sendf(conn->firstsocket, conn,
|
||||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
||||||
"DEFINE "
|
"DEFINE "
|
||||||
"%s " /* database */
|
"%s " /* database */
|
||||||
"%s\n" /* word */
|
"%s\n" /* word */
|
||||||
"QUIT\n",
|
"QUIT\n",
|
||||||
|
database,
|
||||||
database,
|
word);
|
||||||
word
|
if(result)
|
||||||
);
|
failf(data, "Failed sending DICT request");
|
||||||
|
else
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
||||||
-1, NULL); /* no upload */
|
-1, NULL); /* no upload */
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
@@ -215,18 +215,17 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
if (ppath[i] == ':')
|
if (ppath[i] == ':')
|
||||||
ppath[i] = ' ';
|
ppath[i] = ' ';
|
||||||
}
|
}
|
||||||
Curl_sendf(conn->firstsocket, conn,
|
result = Curl_sendf(conn->firstsocket, conn,
|
||||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
|
||||||
"%s\n"
|
"%s\n"
|
||||||
"QUIT\n",
|
"QUIT\n", ppath);
|
||||||
ppath);
|
if(result)
|
||||||
|
failf(data, "Failed sending DICT request");
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
else
|
||||||
-1, NULL);
|
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
|
||||||
|
-1, NULL);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,6 +236,6 @@ CURLcode Curl_dict(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -87,6 +87,6 @@ DllMain (
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
10
lib/easy.c
10
lib/easy.c
@@ -293,6 +293,12 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
|||||||
outcurl->progress.flags = data->progress.flags;
|
outcurl->progress.flags = data->progress.flags;
|
||||||
outcurl->progress.callback = data->progress.callback;
|
outcurl->progress.callback = data->progress.callback;
|
||||||
|
|
||||||
|
if(data->cookies)
|
||||||
|
/* If cookies are enabled in the parent handle, we enable them
|
||||||
|
in the clone as well! */
|
||||||
|
outcurl->cookies = Curl_cookie_init(data->cookies->filename,
|
||||||
|
outcurl->cookies);
|
||||||
|
|
||||||
/* duplicate all values in 'change' */
|
/* duplicate all values in 'change' */
|
||||||
if(data->change.url) {
|
if(data->change.url) {
|
||||||
outcurl->change.url = strdup(data->change.url);
|
outcurl->change.url = strdup(data->change.url);
|
||||||
@@ -314,6 +320,6 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -115,6 +115,6 @@ char *curl_unescape(const char *string, int length)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -201,6 +201,6 @@ CURLcode Curl_file(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
489
lib/formdata.c
489
lib/formdata.c
@@ -80,6 +80,23 @@ Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
|||||||
Content-Type: text/plain
|
Content-Type: text/plain
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Content-Disposition: form-data; name="ARRAY: FILE1_+_FILE2_+_FILE3"
|
||||||
|
Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
|
||||||
|
...
|
||||||
|
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||||
|
Content-Type: text/plain
|
||||||
|
...
|
||||||
|
Content-Disposition: attachment; filename="Makefile.b32.resp"
|
||||||
|
Content-Type: text/plain
|
||||||
|
...
|
||||||
|
Content-Disposition: attachment; filename="inet_ntoa_r.h"
|
||||||
|
Content-Type: text/plain
|
||||||
|
...
|
||||||
|
|
||||||
|
Content-Disposition: form-data; name="FILECONTENT"
|
||||||
|
...
|
||||||
|
|
||||||
For the old FormParse used by curl_formparse use:
|
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
|
gcc -DHAVE_CONFIG_H -I../ -g -D_OLD_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
|
||||||
@@ -394,7 +411,7 @@ static struct HttpPost * AddHttpPost (char * name,
|
|||||||
if(post) {
|
if(post) {
|
||||||
memset(post, 0, sizeof(struct HttpPost));
|
memset(post, 0, sizeof(struct HttpPost));
|
||||||
post->name = name;
|
post->name = name;
|
||||||
post->namelength = namelength;
|
post->namelength = name?(namelength?namelength:(long)strlen(name)):0;
|
||||||
post->contents = value;
|
post->contents = value;
|
||||||
post->contentslength = contentslength;
|
post->contentslength = contentslength;
|
||||||
post->contenttype = contenttype;
|
post->contenttype = contenttype;
|
||||||
@@ -432,9 +449,9 @@ static struct HttpPost * AddHttpPost (char * name,
|
|||||||
* parent_form_info is NULL.
|
* parent_form_info is NULL.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static FormInfo * AddFormInfo (char *value,
|
static FormInfo * AddFormInfo(char *value,
|
||||||
char *contenttype,
|
char *contenttype,
|
||||||
FormInfo *parent_form_info)
|
FormInfo *parent_form_info)
|
||||||
{
|
{
|
||||||
FormInfo *form_info;
|
FormInfo *form_info;
|
||||||
form_info = (FormInfo *)malloc(sizeof(FormInfo));
|
form_info = (FormInfo *)malloc(sizeof(FormInfo));
|
||||||
@@ -472,7 +489,7 @@ static FormInfo * AddFormInfo (char *value,
|
|||||||
* Returns some valid contenttype for filename.
|
* Returns some valid contenttype for filename.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static const char * ContentTypeForFilename (char *filename,
|
static const char * ContentTypeForFilename (const char *filename,
|
||||||
const char *prevtype)
|
const char *prevtype)
|
||||||
{
|
{
|
||||||
const char *contenttype = NULL;
|
const char *contenttype = NULL;
|
||||||
@@ -528,16 +545,21 @@ static const char * ContentTypeForFilename (char *filename,
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static int AllocAndCopy (char **buffer, int buffer_length)
|
static int AllocAndCopy (char **buffer, int buffer_length)
|
||||||
{
|
{
|
||||||
char *src = *buffer;
|
const char *src = *buffer;
|
||||||
int length;
|
int length, add = 0;
|
||||||
if (buffer_length)
|
if (buffer_length)
|
||||||
length = buffer_length;
|
length = buffer_length;
|
||||||
else
|
else {
|
||||||
length = strlen(*buffer);
|
length = strlen(*buffer);
|
||||||
*buffer = (char*)malloc(length);
|
add = 1;
|
||||||
|
}
|
||||||
|
*buffer = (char*)malloc(length+add);
|
||||||
if (!*buffer)
|
if (!*buffer)
|
||||||
return 1;
|
return 1;
|
||||||
memcpy(*buffer, src, length);
|
memcpy(*buffer, src, length);
|
||||||
|
/* if length unknown do null termination */
|
||||||
|
if (add)
|
||||||
|
(*buffer)[length] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,11 +583,11 @@ static int AllocAndCopy (char **buffer, int buffer_length)
|
|||||||
*
|
*
|
||||||
* Simple name/value pair with copied contents:
|
* Simple name/value pair with copied contents:
|
||||||
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
||||||
* CURLFORM_COPYCONTENTS, "value");
|
* CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
|
||||||
*
|
*
|
||||||
* name/value pair where only the content pointer is remembered:
|
* name/value pair where only the content pointer is remembered:
|
||||||
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
||||||
* CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10);
|
* CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
|
||||||
* (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
|
* (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
|
||||||
*
|
*
|
||||||
* storing a filename (CONTENTTYPE is optional!):
|
* storing a filename (CONTENTTYPE is optional!):
|
||||||
@@ -577,204 +599,301 @@ static int AllocAndCopy (char **buffer, int buffer_length)
|
|||||||
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
|
||||||
* CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
|
* CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
|
||||||
*
|
*
|
||||||
* Returns 0 on success, 1 if the FormInfo allocation fails, 2 if one
|
* Returns:
|
||||||
* option is given twice for one Form, 3 if a null pointer was given for
|
* FORMADD_OK on success
|
||||||
* a char *, 4 if the allocation of a FormInfo struct failed, 5 if an
|
* FORMADD_MEMORY if the FormInfo allocation fails
|
||||||
* unknown option was used, 6 if the some FormInfo is not complete (or
|
* FORMADD_OPTION_TWICE if one option is given twice for one Form
|
||||||
* has an error), 7 if a HttpPost struct cannot be allocated, and 8
|
* FORMADD_NULL if a null pointer was given for a char
|
||||||
* if some allocation for string copying failed.
|
* FORMADD_MEMORY if the allocation of a FormInfo struct failed
|
||||||
|
* FORMADD_UNKNOWN_OPTION if an unknown option was used
|
||||||
|
* FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error)
|
||||||
|
* FORMADD_MEMORY if a HttpPost struct cannot be allocated
|
||||||
|
* FORMADD_MEMORY if some allocation for string copying failed.
|
||||||
|
* FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FORMADD_OK, /* first, no error */
|
||||||
|
|
||||||
|
FORMADD_MEMORY,
|
||||||
|
FORMADD_OPTION_TWICE,
|
||||||
|
FORMADD_NULL,
|
||||||
|
FORMADD_UNKNOWN_OPTION,
|
||||||
|
FORMADD_INCOMPLETE,
|
||||||
|
FORMADD_ILLEGAL_ARRAY,
|
||||||
|
|
||||||
|
FORMADD_LAST /* last */
|
||||||
|
} FORMcode;
|
||||||
|
|
||||||
static
|
static
|
||||||
int FormAdd(struct HttpPost **httppost,
|
FORMcode FormAdd(struct HttpPost **httppost,
|
||||||
struct HttpPost **last_post,
|
struct HttpPost **last_post,
|
||||||
va_list params)
|
va_list params)
|
||||||
{
|
{
|
||||||
FormInfo *first_form_info, *current_form_info, *form_info;
|
FormInfo *first_form, *current_form, *form;
|
||||||
int return_value = 0;
|
FORMcode return_value = FORMADD_OK;
|
||||||
const char *prevtype = NULL;
|
const char *prevtype = NULL;
|
||||||
struct HttpPost *post = NULL;
|
struct HttpPost *post = NULL;
|
||||||
CURLformoption next_option;
|
CURLformoption option;
|
||||||
|
struct curl_forms *forms = NULL;
|
||||||
|
const char *array_value; /* value read from an array */
|
||||||
|
|
||||||
first_form_info = (FormInfo *)malloc(sizeof(struct FormInfo));
|
/* This is a state variable, that if TRUE means that we're parsing an
|
||||||
if(first_form_info) {
|
array that we got passed to us. If FALSE we're parsing the input
|
||||||
memset(first_form_info, 0, sizeof(FormInfo));
|
va_list arguments. */
|
||||||
current_form_info = first_form_info;
|
bool array_state = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to allocate the first struct to fill in.
|
||||||
|
*/
|
||||||
|
first_form = (FormInfo *)malloc(sizeof(struct FormInfo));
|
||||||
|
if(first_form) {
|
||||||
|
memset(first_form, 0, sizeof(FormInfo));
|
||||||
|
current_form = first_form;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 1;
|
return FORMADD_MEMORY;
|
||||||
|
|
||||||
/** TODO: first check whether char * is not NULL
|
/*
|
||||||
TODO: transfer.c
|
* Loop through all the options set.
|
||||||
*/
|
*/
|
||||||
while ( ((next_option = va_arg(params, CURLformoption)) != CURLFORM_END) &&
|
while (1) {
|
||||||
(return_value == 0) )
|
|
||||||
{
|
/* break if we have an error to report */
|
||||||
switch (next_option)
|
if (return_value != FORMADD_OK)
|
||||||
{
|
break;
|
||||||
case CURLFORM_PTRNAME:
|
|
||||||
current_form_info->flags |= HTTPPOST_PTRNAME; /* fall through */
|
/* first see if we have more parts of the array param */
|
||||||
case CURLFORM_COPYNAME:
|
if ( array_state ) {
|
||||||
if (current_form_info->name)
|
/* get the upcoming option from the given array */
|
||||||
return_value = 2;
|
option = forms->option;
|
||||||
else {
|
array_value = forms->value;
|
||||||
if (next_option == CURLFORM_PTRNAME)
|
|
||||||
current_form_info->name = va_arg(params, char *);
|
forms++; /* advance this to next entry */
|
||||||
else {
|
if (CURLFORM_END == option) {
|
||||||
char *name = va_arg(params, char *);
|
/* end of array state */
|
||||||
if (name)
|
array_state = FALSE;
|
||||||
current_form_info->name = name; /* store for the moment */
|
continue;
|
||||||
else
|
}
|
||||||
return_value = 3;
|
else {
|
||||||
}
|
/* check that the option is OK in an array */
|
||||||
|
|
||||||
|
/* Daniel's note: do we really need to do this? */
|
||||||
|
if ( (option <= CURLFORM_ARRAY_START) ||
|
||||||
|
(option >= CURLFORM_ARRAY_END) ) {
|
||||||
|
return_value = FORMADD_ILLEGAL_ARRAY;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* This is not array-state, get next option */
|
||||||
|
option = va_arg(params, CURLformoption);
|
||||||
|
if (CURLFORM_END == option)
|
||||||
break;
|
break;
|
||||||
case CURLFORM_NAMELENGTH:
|
}
|
||||||
if (current_form_info->namelength)
|
|
||||||
return_value = 2;
|
switch (option) {
|
||||||
|
case CURLFORM_ARRAY:
|
||||||
|
forms = va_arg(params, struct curl_forms *);
|
||||||
|
if (forms)
|
||||||
|
array_state = TRUE;
|
||||||
|
else
|
||||||
|
return_value = FORMADD_NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the Name property.
|
||||||
|
*/
|
||||||
|
case CURLFORM_PTRNAME:
|
||||||
|
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
|
||||||
|
case CURLFORM_COPYNAME:
|
||||||
|
if (current_form->name)
|
||||||
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
|
else {
|
||||||
|
char *name = va_arg(params, char *);
|
||||||
|
if (name)
|
||||||
|
current_form->name = name; /* store for the moment */
|
||||||
else
|
else
|
||||||
current_form_info->namelength = va_arg(params, long);
|
return_value = FORMADD_NULL;
|
||||||
break;
|
}
|
||||||
case CURLFORM_PTRCONTENTS:
|
break;
|
||||||
current_form_info->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
|
case CURLFORM_NAMELENGTH:
|
||||||
case CURLFORM_COPYCONTENTS:
|
if (current_form->namelength)
|
||||||
if (current_form_info->value)
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
return_value = 2;
|
else
|
||||||
else {
|
current_form->namelength = va_arg(params, long);
|
||||||
if (next_option == CURLFORM_PTRCONTENTS)
|
break;
|
||||||
current_form_info->value = va_arg(params, char *);
|
|
||||||
else {
|
/*
|
||||||
char *value = va_arg(params, char *);
|
* Set the contents property.
|
||||||
if (value)
|
*/
|
||||||
current_form_info->value = value; /* store for the moment */
|
case CURLFORM_PTRCONTENTS:
|
||||||
else
|
current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
|
||||||
return_value = 3;
|
case CURLFORM_COPYCONTENTS:
|
||||||
}
|
if (current_form->value)
|
||||||
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
|
else {
|
||||||
|
char *value = va_arg(params, char *);
|
||||||
|
if (value)
|
||||||
|
current_form->value = value; /* store for the moment */
|
||||||
|
else
|
||||||
|
return_value = FORMADD_NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CURLFORM_CONTENTSLENGTH:
|
||||||
|
if (current_form->contentslength)
|
||||||
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
|
else
|
||||||
|
current_form->contentslength = va_arg(params, long);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get contents from a given file name */
|
||||||
|
case CURLFORM_FILECONTENT:
|
||||||
|
if (current_form->flags != 0)
|
||||||
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
|
else {
|
||||||
|
char *filename = va_arg(params, char *);
|
||||||
|
if (filename) {
|
||||||
|
current_form->value = strdup(filename);
|
||||||
|
current_form->flags |= HTTPPOST_READFILE;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case CURLFORM_CONTENTSLENGTH:
|
|
||||||
if (current_form_info->contentslength)
|
|
||||||
return_value = 2;
|
|
||||||
else
|
else
|
||||||
current_form_info->contentslength = va_arg(params, long);
|
return_value = FORMADD_NULL;
|
||||||
break;
|
}
|
||||||
case CURLFORM_FILE: {
|
break;
|
||||||
char *filename = va_arg(params, char *);
|
|
||||||
if (current_form_info->value) {
|
/* We upload a file */
|
||||||
if (current_form_info->flags & HTTPPOST_FILENAME) {
|
case CURLFORM_FILE:
|
||||||
if (filename) {
|
{
|
||||||
if (!(current_form_info = AddFormInfo (strdup(filename),
|
const char *filename = NULL;
|
||||||
NULL, current_form_info)))
|
if (array_state)
|
||||||
return_value = 4;
|
filename = array_value;
|
||||||
}
|
else
|
||||||
else
|
filename = va_arg(params, const char *);
|
||||||
return_value = 3;
|
if (current_form->value) {
|
||||||
|
if (current_form->flags & HTTPPOST_FILENAME) {
|
||||||
|
if (filename) {
|
||||||
|
if (!(current_form = AddFormInfo(strdup(filename),
|
||||||
|
NULL, current_form)))
|
||||||
|
return_value = FORMADD_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return_value = FORMADD_NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return_value = 2;
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (filename)
|
if (filename)
|
||||||
current_form_info->value = strdup(filename);
|
current_form->value = strdup(filename);
|
||||||
else
|
else
|
||||||
return_value = 3;
|
return_value = FORMADD_NULL;
|
||||||
current_form_info->flags |= HTTPPOST_FILENAME;
|
current_form->flags |= HTTPPOST_FILENAME;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CURLFORM_CONTENTTYPE: {
|
case CURLFORM_CONTENTTYPE:
|
||||||
char *contenttype = va_arg(params, char *);
|
{
|
||||||
if (current_form_info->contenttype) {
|
const char *contenttype = NULL;
|
||||||
if (current_form_info->flags & HTTPPOST_FILENAME) {
|
if (array_state)
|
||||||
|
contenttype = array_value;
|
||||||
|
else
|
||||||
|
contenttype = va_arg(params, const char *);
|
||||||
|
if (current_form->contenttype) {
|
||||||
|
if (current_form->flags & HTTPPOST_FILENAME) {
|
||||||
if (contenttype) {
|
if (contenttype) {
|
||||||
if (!(current_form_info = AddFormInfo (NULL,
|
if (!(current_form = AddFormInfo(NULL,
|
||||||
strdup(contenttype),
|
strdup(contenttype),
|
||||||
current_form_info)))
|
current_form)))
|
||||||
return_value = 4;
|
return_value = FORMADD_MEMORY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return_value = 3;
|
return_value = FORMADD_NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return_value = 2;
|
return_value = FORMADD_OPTION_TWICE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (contenttype)
|
if (contenttype)
|
||||||
current_form_info->contenttype = strdup(contenttype);
|
current_form->contenttype = strdup(contenttype);
|
||||||
else
|
else
|
||||||
return_value = 3;
|
return_value = FORMADD_NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", next_option);
|
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
|
||||||
return_value = 5;
|
return_value = FORMADD_UNKNOWN_OPTION;
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/* go through the list, check for copleteness and if everything is
|
|
||||||
* alright add the HttpPost item otherwise set return_value accordingly */
|
|
||||||
form_info = first_form_info;
|
|
||||||
while (form_info != NULL)
|
|
||||||
{
|
|
||||||
if ( (!first_form_info->name) ||
|
|
||||||
(!form_info->value) ||
|
|
||||||
( (!form_info->namelength) &&
|
|
||||||
(form_info->flags & HTTPPOST_PTRNAME) ) ||
|
|
||||||
( (form_info->contentslength) &&
|
|
||||||
(form_info->flags & HTTPPOST_FILENAME) ) ||
|
|
||||||
( (form_info->flags & HTTPPOST_FILENAME) &&
|
|
||||||
(form_info->flags & HTTPPOST_PTRCONTENTS) )
|
|
||||||
) {
|
|
||||||
return_value = 6;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
if ( (form_info->flags & HTTPPOST_FILENAME) &&
|
|
||||||
(!form_info->contenttype) ) {
|
|
||||||
/* our contenttype is missing */
|
|
||||||
form_info->contenttype
|
|
||||||
= strdup(ContentTypeForFilename(form_info->value, prevtype));
|
|
||||||
}
|
|
||||||
if ( !(form_info->flags & HTTPPOST_PTRNAME) &&
|
|
||||||
(form_info == first_form_info) ) {
|
|
||||||
/* copy name (without strdup; possibly contains null characters) */
|
|
||||||
if (AllocAndCopy(&form_info->name, form_info->namelength)) {
|
|
||||||
return_value = 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !(form_info->flags & HTTPPOST_FILENAME) &&
|
|
||||||
!(form_info->flags & HTTPPOST_PTRCONTENTS) ) {
|
|
||||||
/* copy value (without strdup; possibly contains null characters) */
|
|
||||||
if (AllocAndCopy(&form_info->value, form_info->contentslength)) {
|
|
||||||
return_value = 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( (post = AddHttpPost (form_info->name, form_info->namelength,
|
|
||||||
form_info->value, form_info->contentslength,
|
|
||||||
form_info->contenttype, form_info->flags,
|
|
||||||
post, httppost,
|
|
||||||
last_post)) == NULL) {
|
|
||||||
return_value = 7;
|
|
||||||
}
|
|
||||||
if (form_info->contenttype)
|
|
||||||
prevtype = form_info->contenttype;
|
|
||||||
}
|
|
||||||
form_info = form_info->more;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* and finally delete the allocated memory */
|
if(FORMADD_OK == return_value) {
|
||||||
form_info = first_form_info;
|
/* go through the list, check for copleteness and if everything is
|
||||||
while (form_info != NULL) {
|
* alright add the HttpPost item otherwise set return_value accordingly */
|
||||||
FormInfo *delete_form_info;
|
|
||||||
|
|
||||||
delete_form_info = form_info;
|
post = NULL;
|
||||||
form_info = form_info->more;
|
for(form = first_form;
|
||||||
free (delete_form_info);
|
form != NULL;
|
||||||
};
|
form = form->more) {
|
||||||
|
if ( ((!form->name || !form->value) && !post) ||
|
||||||
|
( (form->contentslength) &&
|
||||||
|
(form->flags & HTTPPOST_FILENAME) ) ||
|
||||||
|
( (form->flags & HTTPPOST_FILENAME) &&
|
||||||
|
(form->flags & HTTPPOST_PTRCONTENTS) ) ||
|
||||||
|
( (form->flags & HTTPPOST_READFILE) &&
|
||||||
|
(form->flags & HTTPPOST_PTRCONTENTS) )
|
||||||
|
) {
|
||||||
|
return_value = FORMADD_INCOMPLETE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( (form->flags & HTTPPOST_FILENAME) &&
|
||||||
|
!form->contenttype ) {
|
||||||
|
/* our contenttype is missing */
|
||||||
|
form->contenttype
|
||||||
|
= strdup(ContentTypeForFilename(form->value, prevtype));
|
||||||
|
}
|
||||||
|
if ( !(form->flags & HTTPPOST_PTRNAME) &&
|
||||||
|
(form == first_form) ) {
|
||||||
|
/* copy name (without strdup; possibly contains null characters) */
|
||||||
|
if (AllocAndCopy(&form->name, form->namelength)) {
|
||||||
|
return_value = FORMADD_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !(form->flags & HTTPPOST_FILENAME) &&
|
||||||
|
!(form->flags & HTTPPOST_READFILE) &&
|
||||||
|
!(form->flags & HTTPPOST_PTRCONTENTS) ) {
|
||||||
|
/* copy value (without strdup; possibly contains null characters) */
|
||||||
|
if (AllocAndCopy(&form->value, form->contentslength)) {
|
||||||
|
return_value = FORMADD_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( (post = AddHttpPost(form->name, form->namelength,
|
||||||
|
form->value, form->contentslength,
|
||||||
|
form->contenttype, form->flags,
|
||||||
|
post, httppost,
|
||||||
|
last_post)) == NULL) {
|
||||||
|
return_value = FORMADD_MEMORY;
|
||||||
|
}
|
||||||
|
if (form->contenttype)
|
||||||
|
prevtype = form->contenttype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always delete the allocated memory before returning */
|
||||||
|
form = first_form;
|
||||||
|
while (form != NULL) {
|
||||||
|
FormInfo *delete_form;
|
||||||
|
|
||||||
|
delete_form = form;
|
||||||
|
form = form->more;
|
||||||
|
free (delete_form);
|
||||||
|
}
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
@@ -1169,6 +1288,8 @@ int main()
|
|||||||
char name7[] = "FILE1_+_CONTENTTYPE";
|
char name7[] = "FILE1_+_CONTENTTYPE";
|
||||||
char name8[] = "FILE1_+_FILE2";
|
char name8[] = "FILE1_+_FILE2";
|
||||||
char name9[] = "FILE1_+_FILE2_+_FILE3";
|
char name9[] = "FILE1_+_FILE2_+_FILE3";
|
||||||
|
char name10[] = "ARRAY: FILE1_+_FILE2_+_FILE3";
|
||||||
|
char name11[] = "FILECONTENT";
|
||||||
char value1[] = "value for simple COPYCONTENTS";
|
char value1[] = "value for simple COPYCONTENTS";
|
||||||
char value2[] = "value for COPYCONTENTS + CONTENTTYPE";
|
char value2[] = "value for COPYCONTENTS + CONTENTTYPE";
|
||||||
char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH";
|
char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH";
|
||||||
@@ -1190,6 +1311,7 @@ int main()
|
|||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
struct HttpPost *httppost=NULL;
|
struct HttpPost *httppost=NULL;
|
||||||
struct HttpPost *last_post=NULL;
|
struct HttpPost *last_post=NULL;
|
||||||
|
struct curl_forms forms[4];
|
||||||
|
|
||||||
struct FormData *form;
|
struct FormData *form;
|
||||||
struct Form formread;
|
struct Form formread;
|
||||||
@@ -1244,6 +1366,21 @@ int main()
|
|||||||
CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7,
|
CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7,
|
||||||
CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END))
|
CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END))
|
||||||
++errors;
|
++errors;
|
||||||
|
forms[0].option = CURLFORM_FILE;
|
||||||
|
forms[0].value = value7;
|
||||||
|
forms[1].option = CURLFORM_FILE;
|
||||||
|
forms[1].value = value8;
|
||||||
|
forms[2].option = CURLFORM_FILE;
|
||||||
|
forms[2].value = value7;
|
||||||
|
forms[3].option = CURLFORM_END;
|
||||||
|
if (FormAddTest("FILE1 + FILE2 + FILE3 ARRAY test", &httppost, &last_post,
|
||||||
|
CURLFORM_COPYNAME, name10, CURLFORM_ARRAY, forms,
|
||||||
|
CURLFORM_END))
|
||||||
|
++errors;
|
||||||
|
if (FormAddTest("FILECONTENT test", &httppost, &last_post,
|
||||||
|
CURLFORM_COPYNAME, name11, CURLFORM_FILECONTENT, value7,
|
||||||
|
CURLFORM_END))
|
||||||
|
++errors;
|
||||||
|
|
||||||
form=Curl_getFormData(httppost, &size);
|
form=Curl_getFormData(httppost, &size);
|
||||||
|
|
||||||
@@ -1255,12 +1392,12 @@ int main()
|
|||||||
|
|
||||||
if(-1 == nread)
|
if(-1 == nread)
|
||||||
break;
|
break;
|
||||||
fwrite(buffer, nread, 1, stderr);
|
fwrite(buffer, nread, 1, stdout);
|
||||||
} while(1);
|
} while(1);
|
||||||
|
|
||||||
fprintf(stderr, "size: %d\n", size);
|
fprintf(stdout, "size: %d\n", size);
|
||||||
if (errors)
|
if (errors)
|
||||||
fprintf(stderr, "\n==> %d Test(s) failed!\n", errors);
|
fprintf(stdout, "\n==> %d Test(s) failed!\n", errors);
|
||||||
else
|
else
|
||||||
fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n");
|
fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n");
|
||||||
|
|
||||||
@@ -1327,6 +1464,6 @@ int main(int argc, char **argv)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -28,11 +28,10 @@ CURLcode Curl_ftp_done(struct connectdata *conn);
|
|||||||
CURLcode Curl_ftp_connect(struct connectdata *conn);
|
CURLcode Curl_ftp_connect(struct connectdata *conn);
|
||||||
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
|
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
|
||||||
|
|
||||||
size_t Curl_ftpsendf(int fd, struct connectdata *, const char *fmt, ...);
|
size_t Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
|
||||||
|
|
||||||
/* The kerberos stuff needs this: */
|
/* The kerberos stuff needs this: */
|
||||||
int Curl_GetFTPResponse(int sockfd, char *buf,
|
int Curl_GetFTPResponse(char *buf, struct connectdata *conn,
|
||||||
struct connectdata *conn,
|
|
||||||
int *ftpcode);
|
int *ftpcode);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2131,6 +2131,6 @@ main (ac, av)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -71,6 +71,6 @@ char *curl_getenv(const char *v)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -46,7 +46,7 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
|
|||||||
|
|
||||||
info->httpcode = 0;
|
info->httpcode = 0;
|
||||||
info->httpversion=0;
|
info->httpversion=0;
|
||||||
info->filetime=0;
|
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
@@ -138,6 +138,6 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -249,6 +249,6 @@ char *getpass(const char *prompt)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
205
lib/hostip.c
205
lib/hostip.c
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
#include "hostip.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"
|
||||||
@@ -65,8 +66,168 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a wrapper function for freeing name information in a protocol
|
||||||
|
* independent way. This takes care of using the appropriate underlaying
|
||||||
|
* proper function.
|
||||||
|
*/
|
||||||
|
void Curl_freeaddrinfo(void *freethis)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
freeaddrinfo(freethis);
|
||||||
|
#else
|
||||||
|
free(freethis);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* --- resolve name or IP-number --- */
|
/* --- resolve name or IP-number --- */
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* These two 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 struct types I didn't wanna include
|
||||||
|
* in memdebug.c
|
||||||
|
*/
|
||||||
|
int curl_getaddrinfo(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, *result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
|
||||||
|
source, line);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void curl_freeaddrinfo(struct addrinfo *freethis,
|
||||||
|
int line, const char *source)
|
||||||
|
{
|
||||||
|
(freeaddrinfo)(freethis);
|
||||||
|
if(logfile)
|
||||||
|
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
|
||||||
|
source, line, freethis);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 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 meory *MUST* be freed with
|
||||||
|
* Curl_freeaddrinfo(), nothing else.
|
||||||
|
*/
|
||||||
|
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
char **bufp)
|
||||||
|
{
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
int error;
|
||||||
|
char sbuf[NI_MAXSERV];
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = PF_UNSPEC;
|
||||||
|
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\n", hostname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*bufp=(char *)res; /* make it point to the result struct */
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#else /* following code is IPv4-only */
|
||||||
|
|
||||||
|
#ifndef HAVE_GETHOSTBYNAME_R
|
||||||
|
/**
|
||||||
|
* Performs a "deep" copy of a hostent into a buffer (returns a pointer to the
|
||||||
|
* copy). Make absolutely sure the destination buffer is big enough!
|
||||||
|
*
|
||||||
|
* Keith McGuigan
|
||||||
|
* 10/3/2001 */
|
||||||
|
static struct hostent* pack_hostent(char* buf, struct hostent* orig)
|
||||||
|
{
|
||||||
|
char* bufptr;
|
||||||
|
struct hostent* copy;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char* str;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
bufptr = buf;
|
||||||
|
copy = (struct hostent*)bufptr;
|
||||||
|
|
||||||
|
bufptr += sizeof(struct hostent);
|
||||||
|
copy->h_name = bufptr;
|
||||||
|
len = strlen(orig->h_name) + 1;
|
||||||
|
strncpy(bufptr, orig->h_name, len);
|
||||||
|
bufptr += len;
|
||||||
|
|
||||||
|
/* we align on even 64bit boundaries for safety */
|
||||||
|
#define MEMALIGN(x) (((unsigned long)(x)&0xfffffff8)+8)
|
||||||
|
|
||||||
|
/* This must be aligned properly to work on many CPU architectures! */
|
||||||
|
copy->h_aliases = (char**)MEMALIGN(bufptr);
|
||||||
|
|
||||||
|
/* Figure out how many aliases there are */
|
||||||
|
for (i = 0; orig->h_aliases[i] != NULL; ++i);
|
||||||
|
|
||||||
|
/* Reserve room for the array */
|
||||||
|
bufptr += (i + 1) * sizeof(char*);
|
||||||
|
|
||||||
|
/* Clone all known aliases */
|
||||||
|
for(i = 0; (str = orig->h_aliases[i]); i++) {
|
||||||
|
len = strlen(str) + 1;
|
||||||
|
strncpy(bufptr, str, len);
|
||||||
|
copy->h_aliases[i] = bufptr;
|
||||||
|
bufptr += len;
|
||||||
|
}
|
||||||
|
/* Terminate the alias list with a NULL */
|
||||||
|
copy->h_aliases[i] = NULL;
|
||||||
|
|
||||||
|
copy->h_addrtype = orig->h_addrtype;
|
||||||
|
copy->h_length = orig->h_length;
|
||||||
|
|
||||||
|
/* align it for (at least) 32bit accesses */
|
||||||
|
bufptr = (char *)MEMALIGN(bufptr);
|
||||||
|
|
||||||
|
copy->h_addr_list = (char**)bufptr;
|
||||||
|
|
||||||
|
/* Figure out how many addresses there are */
|
||||||
|
for (i = 0; orig->h_addr_list[i] != NULL; ++i);
|
||||||
|
|
||||||
|
/* Reserve room for the array */
|
||||||
|
bufptr += (i + 1) * sizeof(char*);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
len = orig->h_length;
|
||||||
|
str = orig->h_addr_list[i];
|
||||||
|
while (str != NULL) {
|
||||||
|
memcpy(bufptr, str, len);
|
||||||
|
copy->h_addr_list[i] = bufptr;
|
||||||
|
bufptr += len;
|
||||||
|
str = orig->h_addr_list[++i];
|
||||||
|
}
|
||||||
|
copy->h_addr_list[i] = NULL;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *MakeIP(unsigned long num,char *addr, int addr_len)
|
static char *MakeIP(unsigned long num,char *addr, int addr_len)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
|
#if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
|
||||||
@@ -88,29 +249,6 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len)
|
|||||||
return (addr);
|
return (addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
struct addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|
||||||
char *hostname,
|
|
||||||
int port)
|
|
||||||
{
|
|
||||||
struct addrinfo hints, *res;
|
|
||||||
int error;
|
|
||||||
char sbuf[NI_MAXSERV];
|
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = PF_UNSPEC;
|
|
||||||
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\n", hostname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The original code to this function was once stolen from the Dancer source
|
/* 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
|
code, written by Bjorn Reese, it has since been patched and modified
|
||||||
considerably. */
|
considerably. */
|
||||||
@@ -119,9 +257,10 @@ struct addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
#define INADDR_NONE (unsigned long) ~0
|
#define INADDR_NONE (unsigned long) ~0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct hostent *Curl_gethost(struct SessionHandle *data,
|
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
char **bufp)
|
int port,
|
||||||
|
char **bufp)
|
||||||
{
|
{
|
||||||
struct hostent *h = NULL;
|
struct hostent *h = NULL;
|
||||||
unsigned long in;
|
unsigned long in;
|
||||||
@@ -137,6 +276,7 @@ struct hostent *Curl_gethost(struct SessionHandle *data,
|
|||||||
return NULL; /* major failure */
|
return NULL; /* major failure */
|
||||||
*bufp = buf;
|
*bufp = buf;
|
||||||
|
|
||||||
|
port=0; /* unused in IPv4 code */
|
||||||
ret = 0; /* to prevent the compiler warning */
|
ret = 0; /* to prevent the compiler warning */
|
||||||
|
|
||||||
if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
|
if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
|
||||||
@@ -211,15 +351,22 @@ struct hostent *Curl_gethost(struct SessionHandle *data,
|
|||||||
free(buf);
|
free(buf);
|
||||||
*bufp=NULL;
|
*bufp=NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
/* we make a copy of the hostent right now, right here, as the
|
||||||
|
static one we got a pointer to might get removed when we don't
|
||||||
|
want/expect that */
|
||||||
|
h = pack_hostent(buf, h);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return (h);
|
return (h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* end of IPv4-specific code */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
24
lib/hostip.h
24
lib/hostip.h
@@ -24,12 +24,24 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
struct hostent;
|
||||||
char *hostname,
|
struct SessionHandle;
|
||||||
int port);
|
|
||||||
|
|
||||||
struct hostent *Curl_gethost(struct SessionHandle *data,
|
/* Get name info */
|
||||||
char *hostname,
|
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
||||||
char **bufp);
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
char **bufp);
|
||||||
|
/* free name info */
|
||||||
|
void Curl_freeaddrinfo(void *freethis);
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
void curl_freeaddrinfo(struct addrinfo *freethis,
|
||||||
|
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
|
#endif
|
||||||
|
103
lib/http.c
103
lib/http.c
@@ -125,22 +125,27 @@ send_buffer *add_buffer_init(void)
|
|||||||
* add_buffer_send() sends a buffer and frees all associated memory.
|
* add_buffer_send() sends a buffer and frees all associated memory.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in)
|
CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
|
||||||
|
long *bytes_written)
|
||||||
{
|
{
|
||||||
size_t amount;
|
size_t amount;
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
if(conn->data->set.verbose) {
|
if(conn->data->set.verbose) {
|
||||||
fputs("> ", conn->data->set.err);
|
fputs("> ", conn->data->set.err);
|
||||||
/* this data _may_ contain binary stuff */
|
/* this data _may_ contain binary stuff */
|
||||||
fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
|
fwrite(in->buffer, in->size_used, 1, conn->data->set.err);
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_write(conn, sockfd, in->buffer, in->size_used, &amount);
|
result = Curl_write(conn, sockfd, in->buffer, in->size_used, &amount);
|
||||||
|
|
||||||
if(in->buffer)
|
if(in->buffer)
|
||||||
free(in->buffer);
|
free(in->buffer);
|
||||||
free(in);
|
free(in);
|
||||||
|
|
||||||
return amount;
|
*bytes_written = amount;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -251,19 +256,25 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
|||||||
int httperror=0;
|
int httperror=0;
|
||||||
int subversion=0;
|
int subversion=0;
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
|
CURLcode result;
|
||||||
|
|
||||||
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
|
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
|
||||||
|
|
||||||
/* OK, now send the connect request to the proxy */
|
/* OK, now send the connect request to the proxy */
|
||||||
Curl_sendf(tunnelsocket, conn,
|
result =
|
||||||
"CONNECT %s:%d HTTP/1.0\015\012"
|
Curl_sendf(tunnelsocket, conn,
|
||||||
"%s"
|
"CONNECT %s:%d HTTP/1.0\015\012"
|
||||||
"%s"
|
"%s"
|
||||||
"\r\n",
|
"%s"
|
||||||
hostname, remote_port,
|
"\r\n",
|
||||||
(conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
|
hostname, remote_port,
|
||||||
(data->set.useragent?conn->allocptr.uagent:"")
|
(conn->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
|
||||||
);
|
(data->set.useragent?conn->allocptr.uagent:"")
|
||||||
|
);
|
||||||
|
if(result) {
|
||||||
|
failf(data, "Failed sending CONNECT to proxy");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
|
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
|
||||||
while(GetLine(tunnelsocket, data->state.buffer, conn)) {
|
while(GetLine(tunnelsocket, data->state.buffer, conn)) {
|
||||||
@@ -352,6 +363,13 @@ CURLcode Curl_http_done(struct connectdata *conn)
|
|||||||
*bytecount = http->readbytecount + http->writebytecount;
|
*bytecount = http->readbytecount + http->writebytecount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(0 == (http->readbytecount + conn->headerbytecount)) {
|
||||||
|
/* nothing was read from the HTTP server, this can't be right
|
||||||
|
so we return an error here */
|
||||||
|
failf(data, "Empty reply from server\n");
|
||||||
|
return CURLE_GOT_NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +573,10 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
/* Use 1.1 unless the use specificly asked for 1.0 */
|
||||||
|
const char *httpstring=
|
||||||
|
data->set.httpversion==CURL_HTTP_VERSION_1_0?"1.0":"1.1";
|
||||||
|
|
||||||
send_buffer *req_buffer;
|
send_buffer *req_buffer;
|
||||||
struct curl_slist *headers=data->set.headers;
|
struct curl_slist *headers=data->set.headers;
|
||||||
|
|
||||||
@@ -564,7 +586,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
/* add the main request stuff */
|
/* add the main request stuff */
|
||||||
add_bufferf(req_buffer,
|
add_bufferf(req_buffer,
|
||||||
"%s " /* GET/HEAD/POST/PUT */
|
"%s " /* GET/HEAD/POST/PUT */
|
||||||
"%s HTTP/1.1\r\n" /* path */
|
"%s HTTP/%s\r\n" /* path */
|
||||||
"%s" /* proxyuserpwd */
|
"%s" /* proxyuserpwd */
|
||||||
"%s" /* userpwd */
|
"%s" /* userpwd */
|
||||||
"%s" /* range */
|
"%s" /* range */
|
||||||
@@ -580,7 +602,7 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
((HTTPREQ_POST == data->set.httpreq) ||
|
((HTTPREQ_POST == data->set.httpreq) ||
|
||||||
(HTTPREQ_POST_FORM == data->set.httpreq))?"POST":
|
(HTTPREQ_POST_FORM == data->set.httpreq))?"POST":
|
||||||
(HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"),
|
(HTTPREQ_PUT == data->set.httpreq)?"PUT":"GET"),
|
||||||
ppath,
|
ppath, httpstring,
|
||||||
(conn->bits.proxy_user_passwd &&
|
(conn->bits.proxy_user_passwd &&
|
||||||
conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
|
conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
|
||||||
(conn->bits.user_passwd && conn->allocptr.userpwd)?
|
(conn->bits.user_passwd && conn->allocptr.userpwd)?
|
||||||
@@ -729,14 +751,16 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
Curl_pgrsSetUploadSize(data, http->postsize);
|
Curl_pgrsSetUploadSize(data, http->postsize);
|
||||||
|
|
||||||
/* fire away the whole request to the server */
|
/* fire away the whole request to the server */
|
||||||
data->info.request_size =
|
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
|
||||||
add_buffer_send(conn->firstsocket, conn, req_buffer);
|
&data->info.request_size);
|
||||||
|
if(result)
|
||||||
/* setup variables for the upcoming transfer */
|
failf(data, "Failed sending POST request");
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
|
else
|
||||||
&http->readbytecount,
|
/* setup variables for the upcoming transfer */
|
||||||
conn->firstsocket,
|
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
|
||||||
&http->writebytecount);
|
&http->readbytecount,
|
||||||
|
conn->firstsocket,
|
||||||
|
&http->writebytecount);
|
||||||
if(result) {
|
if(result) {
|
||||||
Curl_formclean(http->sendit); /* free that whole lot */
|
Curl_formclean(http->sendit); /* free that whole lot */
|
||||||
return result;
|
return result;
|
||||||
@@ -757,14 +781,16 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||||
|
|
||||||
/* this sends the buffer and frees all the buffer resources */
|
/* this sends the buffer and frees all the buffer resources */
|
||||||
data->info.request_size =
|
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
|
||||||
add_buffer_send(conn->firstsocket, conn, req_buffer);
|
&data->info.request_size);
|
||||||
|
if(result)
|
||||||
/* prepare for transfer */
|
failf(data, "Faied sending POST request");
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
|
else
|
||||||
&http->readbytecount,
|
/* prepare for transfer */
|
||||||
conn->firstsocket,
|
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
|
||||||
&http->writebytecount);
|
&http->readbytecount,
|
||||||
|
conn->firstsocket,
|
||||||
|
&http->writebytecount);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -814,12 +840,15 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
add_buffer(req_buffer, "\r\n", 2);
|
add_buffer(req_buffer, "\r\n", 2);
|
||||||
|
|
||||||
/* issue the request */
|
/* issue the request */
|
||||||
data->info.request_size =
|
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
|
||||||
add_buffer_send(conn->firstsocket, conn, req_buffer);
|
&data->info.request_size);
|
||||||
|
|
||||||
/* HTTP GET/HEAD download: */
|
if(result)
|
||||||
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
|
failf(data, "Failed sending HTTP request");
|
||||||
-1, NULL); /* nothing to upload */
|
else
|
||||||
|
/* HTTP GET/HEAD download: */
|
||||||
|
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
|
||||||
|
-1, NULL); /* nothing to upload */
|
||||||
}
|
}
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
@@ -834,6 +863,6 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -225,6 +225,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -129,6 +129,6 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
28
lib/krb4.c
28
lib/krb4.c
@@ -194,7 +194,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
|||||||
u_int32_t cs;
|
u_int32_t cs;
|
||||||
struct krb4_data *d = app_data;
|
struct krb4_data *d = app_data;
|
||||||
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
|
||||||
char *host = conn->hp->h_name;
|
char *host = conn->hostaddr->h_name;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int l = sizeof(conn->local_addr);
|
int l = sizeof(conn->local_addr);
|
||||||
|
|
||||||
@@ -245,12 +245,12 @@ krb4_auth(void *app_data, struct connectdata *conn)
|
|||||||
return AUTH_CONTINUE;
|
return AUTH_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_ftpsendf(conn->firstsocket, conn, "ADAT %s", p);
|
if(Curl_ftpsendf(conn, "ADAT %s", p))
|
||||||
|
return -2;
|
||||||
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
|
||||||
conn->data->state.buffer, conn, NULL);
|
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/-1;
|
return -1;
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
||||||
@@ -313,10 +313,10 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
|
|
||||||
save = Curl_set_command_prot(conn, prot_private);
|
save = Curl_set_command_prot(conn, prot_private);
|
||||||
|
|
||||||
Curl_ftpsendf(conn->firstsocket, conn,
|
if(Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user))
|
||||||
"SITE KAUTH %s", conn->data->state.user);
|
return;
|
||||||
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->state.buffer,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer,
|
||||||
conn, NULL);
|
conn, NULL);
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/;
|
return /*CURLE_OPERATION_TIMEOUTED*/;
|
||||||
@@ -363,7 +363,7 @@ void 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(/*hostname*/conn->hp->h_name),
|
krb_realmofhost(conn->hostaddr->h_name),
|
||||||
&key);
|
&key);
|
||||||
des_key_sched (&key, schedule);
|
des_key_sched (&key, schedule);
|
||||||
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
|
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
|
||||||
@@ -380,10 +380,10 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
memset (tktcopy.dat, 0, tktcopy.length);
|
memset (tktcopy.dat, 0, tktcopy.length);
|
||||||
|
|
||||||
Curl_ftpsendf(conn->firstsocket, conn,
|
if(Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p))
|
||||||
"SITE KAUTH %s %s", name, p);
|
return;
|
||||||
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->state.buffer,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer,
|
||||||
conn, NULL);
|
conn, NULL);
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/;
|
return /*CURLE_OPERATION_TIMEOUTED*/;
|
||||||
@@ -397,6 +397,6 @@ void Curl_krb_kauth(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
10
lib/ldap.c
10
lib/ldap.c
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
|
#include "transfer.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -210,6 +211,9 @@ CURLcode Curl_ldap(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DynaClose();
|
DynaClose();
|
||||||
|
|
||||||
|
/* no data to transfer */
|
||||||
|
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -218,6 +222,6 @@ CURLcode Curl_ldap(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -32,4 +32,5 @@ EXPORTS
|
|||||||
curl_strequal @ 23 ;
|
curl_strequal @ 23 ;
|
||||||
curl_strnequal @ 24 ;
|
curl_strnequal @ 24 ;
|
||||||
curl_easy_duphandle @ 25 ;
|
curl_easy_duphandle @ 25 ;
|
||||||
|
curl_formadd @ 26 ;
|
||||||
|
|
||||||
|
@@ -60,15 +60,19 @@ FILE *logfile;
|
|||||||
/* this sets the log file name */
|
/* this sets the log file name */
|
||||||
void curl_memdebug(const char *logname)
|
void curl_memdebug(const char *logname)
|
||||||
{
|
{
|
||||||
logfile = fopen(logname, "w");
|
if(logname)
|
||||||
|
logfile = fopen(logname, "w");
|
||||||
|
else
|
||||||
|
logfile = stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *curl_domalloc(size_t size, int line, const char *source)
|
void *curl_domalloc(size_t size, int line, const char *source)
|
||||||
{
|
{
|
||||||
void *mem=(malloc)(size);
|
void *mem=(malloc)(size);
|
||||||
fprintf(logfile?logfile:stderr, "MEM %s:%d malloc(%d) = %p\n",
|
if(logfile)
|
||||||
source, line, size, mem);
|
fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n",
|
||||||
|
source, line, size, mem);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,16 +89,18 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
|||||||
|
|
||||||
mem=(strdup)(str);
|
mem=(strdup)(str);
|
||||||
len=strlen(str)+1;
|
len=strlen(str)+1;
|
||||||
fprintf(logfile?logfile:stderr, "MEM %s:%d strdup(%p) (%d) = %p\n",
|
if(logfile)
|
||||||
source, line, str, len, mem);
|
fprintf(logfile, "MEM %s:%d strdup(%p) (%d) = %p\n",
|
||||||
|
source, line, str, len, mem);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source)
|
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source)
|
||||||
{
|
{
|
||||||
void *mem=(realloc)(ptr, size);
|
void *mem=(realloc)(ptr, size);
|
||||||
fprintf(logfile?logfile:stderr, "MEM %s:%d realloc(%p, %d) = %p\n",
|
if(logfile)
|
||||||
source, line, ptr, size, mem);
|
fprintf(logfile, "MEM %s:%d realloc(%p, %d) = %p\n",
|
||||||
|
source, line, ptr, size, mem);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,15 +114,16 @@ void curl_dofree(void *ptr, int line, const char *source)
|
|||||||
|
|
||||||
(free)(ptr);
|
(free)(ptr);
|
||||||
|
|
||||||
fprintf(logfile?logfile:stderr, "MEM %s:%d free(%p)\n",
|
if(logfile)
|
||||||
source, line, ptr);
|
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int curl_socket(int domain, int type, int protocol, int line, char *source)
|
int curl_socket(int domain, int type, int protocol, int line, char *source)
|
||||||
{
|
{
|
||||||
int sockfd=(socket)(domain, type, protocol);
|
int sockfd=(socket)(domain, type, protocol);
|
||||||
fprintf(logfile?logfile:stderr, "FD %s:%d socket() = %d\n",
|
if(logfile)
|
||||||
source, line, sockfd);
|
fprintf(logfile, "FD %s:%d socket() = %d\n",
|
||||||
|
source, line, sockfd);
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +131,9 @@ int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
|
|||||||
int line, const char *source)
|
int line, const char *source)
|
||||||
{
|
{
|
||||||
int sockfd=(accept)(s, addr, addrlen);
|
int sockfd=(accept)(s, addr, addrlen);
|
||||||
fprintf(logfile?logfile:stderr, "FD %s:%d accept() = %d\n",
|
if(logfile)
|
||||||
source, line, sockfd);
|
fprintf(logfile, "FD %s:%d accept() = %d\n",
|
||||||
|
source, line, sockfd);
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +141,9 @@ int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
|
|||||||
int curl_sclose(int sockfd, int line, char *source)
|
int curl_sclose(int sockfd, int line, char *source)
|
||||||
{
|
{
|
||||||
int res=sclose(sockfd);
|
int res=sclose(sockfd);
|
||||||
fprintf(logfile?logfile:stderr, "FD %s:%d sclose(%d)\n",
|
if(logfile)
|
||||||
source, line, sockfd);
|
fprintf(logfile, "FD %s:%d sclose(%d)\n",
|
||||||
|
source, line, sockfd);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,16 +151,18 @@ FILE *curl_fopen(const char *file, const char *mode,
|
|||||||
int line, const char *source)
|
int line, const char *source)
|
||||||
{
|
{
|
||||||
FILE *res=(fopen)(file, mode);
|
FILE *res=(fopen)(file, mode);
|
||||||
fprintf(logfile?logfile:stderr, "FILE %s:%d fopen(\"%s\") = %p\n",
|
if(logfile)
|
||||||
source, line, file, res);
|
fprintf(logfile, "FILE %s:%d fopen(\"%s\") = %p\n",
|
||||||
|
source, line, file, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int curl_fclose(FILE *file, int line, const char *source)
|
int curl_fclose(FILE *file, int line, const char *source)
|
||||||
{
|
{
|
||||||
int res=(fclose)(file);
|
int res=(fclose)(file);
|
||||||
fprintf(logfile?logfile:stderr, "FILE %s:%d fclose(%p)\n",
|
if(logfile)
|
||||||
source, line, file);
|
fprintf(logfile, "FILE %s:%d fclose(%p)\n",
|
||||||
|
source, line, file);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +172,6 @@ int curl_fclose(FILE *file, int line, const char *source)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern FILE *logfile;
|
||||||
|
|
||||||
/* memory functions */
|
/* memory functions */
|
||||||
void *curl_domalloc(size_t size, int line, const char *source);
|
void *curl_domalloc(size_t size, int line, const char *source);
|
||||||
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
|
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
|
||||||
@@ -35,6 +37,11 @@ int curl_fclose(FILE *file, int line, const char *source);
|
|||||||
#define accept(sock,addr,len)\
|
#define accept(sock,addr,len)\
|
||||||
curl_accept(sock,addr,len,__LINE__,__FILE__)
|
curl_accept(sock,addr,len,__LINE__,__FILE__)
|
||||||
|
|
||||||
|
#define getaddrinfo(host,serv,hint,res) \
|
||||||
|
curl_getaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
|
||||||
|
#define freeaddrinfo(data) \
|
||||||
|
curl_freeaddrinfo(data,__LINE__,__FILE__)
|
||||||
|
|
||||||
/* sclose is probably already defined, redefine it! */
|
/* sclose is probably already defined, redefine it! */
|
||||||
#undef sclose
|
#undef sclose
|
||||||
#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
|
#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
|
||||||
|
@@ -1237,6 +1237,6 @@ int main()
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -206,6 +206,6 @@ int main(int argc, char **argv)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -70,7 +70,7 @@ static char *max5data(double bytes, char *max5)
|
|||||||
}
|
}
|
||||||
if(bytes < (100*ONE_MEGABYTE)) {
|
if(bytes < (100*ONE_MEGABYTE)) {
|
||||||
/* 'XX.XM' is good as long as we're less than 100 megs */
|
/* 'XX.XM' is good as long as we're less than 100 megs */
|
||||||
sprintf(max5, "%2.1fM", bytes/ONE_MEGABYTE);
|
sprintf(max5, "%4.1fM", bytes/ONE_MEGABYTE);
|
||||||
return max5;
|
return max5;
|
||||||
}
|
}
|
||||||
sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE);
|
sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE);
|
||||||
@@ -118,16 +118,16 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_NAMELOOKUP:
|
case TIMER_NAMELOOKUP:
|
||||||
data->progress.t_nslookup += Curl_tvdiff(Curl_tvnow(),
|
data->progress.t_nslookup +=
|
||||||
data->progress.t_startsingle);
|
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
|
||||||
break;
|
break;
|
||||||
case TIMER_CONNECT:
|
case TIMER_CONNECT:
|
||||||
data->progress.t_connect += Curl_tvdiff(Curl_tvnow(),
|
data->progress.t_connect +=
|
||||||
data->progress.t_startsingle);
|
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
|
||||||
break;
|
break;
|
||||||
case TIMER_PRETRANSFER:
|
case TIMER_PRETRANSFER:
|
||||||
data->progress.t_pretransfer += Curl_tvdiff(Curl_tvnow(),
|
data->progress.t_pretransfer +=
|
||||||
data->progress.t_startsingle);
|
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000;
|
||||||
break;
|
break;
|
||||||
case TIMER_POSTRANSFER:
|
case TIMER_POSTRANSFER:
|
||||||
/* this is the normal end-of-transfer thing */
|
/* this is the normal end-of-transfer thing */
|
||||||
@@ -187,12 +187,14 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
|
|
||||||
double total_transfer;
|
double total_transfer;
|
||||||
double total_expected_transfer;
|
double total_expected_transfer;
|
||||||
|
double timespent;
|
||||||
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
int nowindex = data->progress.speeder_c% CURR_TIME;
|
int nowindex = data->progress.speeder_c% CURR_TIME;
|
||||||
int checkindex;
|
int checkindex;
|
||||||
int count;
|
|
||||||
|
int countindex; /* amount of seconds stored in the speeder array */
|
||||||
|
|
||||||
char time_left[10];
|
char time_left[10];
|
||||||
char time_total[10];
|
char time_total[10];
|
||||||
@@ -222,14 +224,18 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
|
|
||||||
now = Curl_tvnow(); /* what time is it */
|
now = Curl_tvnow(); /* what time is it */
|
||||||
|
|
||||||
/* The exact time spent so far */
|
/* The exact time spent so far (from the start) */
|
||||||
data->progress.timespent = Curl_tvdiff (now, data->progress.start);
|
timespent = (double)Curl_tvdiff (now, data->progress.start)/1000;
|
||||||
|
|
||||||
|
data->progress.timespent = (long)timespent;
|
||||||
|
|
||||||
/* The average download speed this far */
|
/* The average download speed this far */
|
||||||
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
|
data->progress.dlspeed =
|
||||||
|
data->progress.downloaded/(timespent>0.01?timespent:1);
|
||||||
|
|
||||||
/* The average upload speed this far */
|
/* The average upload speed this far */
|
||||||
data->progress.ulspeed = data->progress.uploaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
|
data->progress.ulspeed =
|
||||||
|
data->progress.uploaded/(timespent>0.01?timespent:1);
|
||||||
|
|
||||||
if(data->progress.lastshow == Curl_tvlong(now))
|
if(data->progress.lastshow == Curl_tvlong(now))
|
||||||
return 0; /* never update this more than once a second if the end isn't
|
return 0; /* never update this more than once a second if the end isn't
|
||||||
@@ -237,24 +243,56 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
data->progress.lastshow = now.tv_sec;
|
data->progress.lastshow = now.tv_sec;
|
||||||
|
|
||||||
/* Let's do the "current speed" thing, which should use the fastest
|
/* Let's do the "current speed" thing, which should use the fastest
|
||||||
of the dl/ul speeds */
|
of the dl/ul speeds. Store the fasted speed at entry 'nowindex'. */
|
||||||
data->progress.speeder[ nowindex ] =
|
data->progress.speeder[ nowindex ] =
|
||||||
data->progress.downloaded>data->progress.uploaded?
|
data->progress.downloaded>data->progress.uploaded?
|
||||||
data->progress.downloaded:data->progress.uploaded;
|
data->progress.downloaded:data->progress.uploaded;
|
||||||
data->progress.speeder_c++; /* increase */
|
|
||||||
count = ((data->progress.speeder_c>=CURR_TIME)?
|
|
||||||
CURR_TIME:data->progress.speeder_c) - 1;
|
|
||||||
checkindex = (data->progress.speeder_c>=CURR_TIME)?
|
|
||||||
data->progress.speeder_c%CURR_TIME:0;
|
|
||||||
|
|
||||||
/* find out the average speed the last CURR_TIME seconds */
|
/* remember the exact time for this moment */
|
||||||
data->progress.current_speed =
|
data->progress.speeder_time [ nowindex ] = now;
|
||||||
(data->progress.speeder[nowindex]-
|
|
||||||
data->progress.speeder[checkindex])/(count?count:1);
|
/* advance our speeder_c counter, which is increased every time we get
|
||||||
|
here and we expect it to never wrap as 2^32 is a lot of seconds! */
|
||||||
|
data->progress.speeder_c++;
|
||||||
|
|
||||||
|
/* figure out how many index entries of data we have stored in our speeder
|
||||||
|
array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
|
||||||
|
transfer. Imagine, after one second we have filled in two entries,
|
||||||
|
after two seconds we've filled in three entries etc. */
|
||||||
|
countindex = ((data->progress.speeder_c>=CURR_TIME)?
|
||||||
|
CURR_TIME:data->progress.speeder_c) - 1;
|
||||||
|
|
||||||
|
/* first of all, we don't do this if there's no counted seconds yet */
|
||||||
|
if(countindex) {
|
||||||
|
long span_ms;
|
||||||
|
|
||||||
|
/* Get the index position to compare with the 'nowindex' position.
|
||||||
|
Get the oldest entry possible. While we have less than CURR_TIME
|
||||||
|
entries, the first entry will remain the oldest. */
|
||||||
|
checkindex = (data->progress.speeder_c>=CURR_TIME)?
|
||||||
|
data->progress.speeder_c%CURR_TIME:0;
|
||||||
|
|
||||||
|
/* Figure out the exact time for the time span */
|
||||||
|
span_ms = Curl_tvdiff(now,
|
||||||
|
data->progress.speeder_time[checkindex]);
|
||||||
|
|
||||||
|
/* Calculate the average speed the last 'countindex' seconds */
|
||||||
|
data->progress.current_speed =
|
||||||
|
(data->progress.speeder[nowindex]-
|
||||||
|
data->progress.speeder[checkindex])/((double)span_ms/1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* the first second we use the main average */
|
||||||
|
data->progress.current_speed =
|
||||||
|
(data->progress.ulspeed>data->progress.dlspeed)?
|
||||||
|
data->progress.ulspeed:data->progress.dlspeed;
|
||||||
|
|
||||||
if(data->progress.flags & PGRS_HIDE)
|
if(data->progress.flags & PGRS_HIDE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
else if(data->set.fprogress) {
|
else if(data->set.fprogress) {
|
||||||
|
/* There's a callback set, so we call that instead of writing
|
||||||
|
anything ourselves. This really is the way to go. */
|
||||||
result= data->set.fprogress(data->set.progress_client,
|
result= data->set.fprogress(data->set.progress_client,
|
||||||
data->progress.size_dl,
|
data->progress.size_dl,
|
||||||
data->progress.downloaded,
|
data->progress.downloaded,
|
||||||
@@ -265,7 +303,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out the estimated time of arrival for the upload */
|
/* Figure out the estimated time of arrival for the upload */
|
||||||
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){
|
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){
|
||||||
ulestimate = data->progress.size_ul / data->progress.ulspeed;
|
ulestimate = data->progress.size_ul / data->progress.ulspeed;
|
||||||
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
|
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
|
||||||
@@ -278,12 +316,12 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now figure out which of them that is slower and use for the for
|
/* Now figure out which of them that is slower and use for the for
|
||||||
total estimate! */
|
total estimate! */
|
||||||
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
|
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
|
||||||
|
|
||||||
|
|
||||||
/* If we have a total estimate, we can display that and the expected
|
/* If we have a total estimate, we can display that and the expected
|
||||||
time left */
|
time left */
|
||||||
if(total_estimate) {
|
if(total_estimate) {
|
||||||
time2str(time_left, total_estimate-(int) data->progress.timespent);
|
time2str(time_left, total_estimate-(int) data->progress.timespent);
|
||||||
time2str(time_total, total_estimate);
|
time2str(time_total, total_estimate);
|
||||||
@@ -337,6 +375,6 @@ int Curl_pgrsUpdate(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -413,33 +413,34 @@ sec_prot_internal(struct connectdata *conn, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(level){
|
if(level){
|
||||||
Curl_ftpsendf(conn->firstsocket, conn,
|
if(Curl_ftpsendf(conn, "PBSZ %u", s))
|
||||||
"PBSZ %u", s);
|
return -1;
|
||||||
/* wait for feedback */
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
|
||||||
conn->data->state.buffer, conn, NULL);
|
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/-1;
|
return -1;
|
||||||
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
|
||||||
|
if(conn->data->state.buffer[0] != '2'){
|
||||||
failf(conn->data, "Failed to set protection buffer size.\n");
|
failf(conn->data, "Failed to set protection buffer size.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
conn->buffer_size = s;
|
conn->buffer_size = s;
|
||||||
p = strstr(/*reply_string*/conn->data->state.buffer, "PBSZ=");
|
|
||||||
|
p = strstr(conn->data->state.buffer, "PBSZ=");
|
||||||
if(p)
|
if(p)
|
||||||
sscanf(p, "PBSZ=%u", &s);
|
sscanf(p, "PBSZ=%u", &s);
|
||||||
if(s < conn->buffer_size)
|
if(s < conn->buffer_size)
|
||||||
conn->buffer_size = s;
|
conn->buffer_size = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_ftpsendf(conn->firstsocket, conn,
|
if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"]))
|
||||||
"PROT %c", level["CSEP"]);
|
return -1;
|
||||||
/* wait for feedback */
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
|
||||||
conn->data->state.buffer, conn, NULL);
|
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/-1;
|
return -1;
|
||||||
if(/*ret != COMPLETE*/conn->data->state.buffer[0] != '2'){
|
|
||||||
|
if(conn->data->state.buffer[0] != '2'){
|
||||||
failf(conn->data, "Failed to set protection level.\n");
|
failf(conn->data, "Failed to set protection level.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -473,6 +474,7 @@ Curl_sec_login(struct connectdata *conn)
|
|||||||
struct Curl_sec_client_mech **m;
|
struct Curl_sec_client_mech **m;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
|
int ftpcode;
|
||||||
|
|
||||||
for(m = mechs; *m && (*m)->name; m++) {
|
for(m = mechs; *m && (*m)->name; m++) {
|
||||||
void *tmp;
|
void *tmp;
|
||||||
@@ -489,31 +491,35 @@ Curl_sec_login(struct connectdata *conn)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
infof(data, "Trying %s...\n", (*m)->name);
|
infof(data, "Trying %s...\n", (*m)->name);
|
||||||
/*ret = command("AUTH %s", (*m)->name);***/
|
|
||||||
Curl_ftpsendf(conn->firstsocket, conn,
|
if(Curl_ftpsendf(conn, "AUTH %s", (*m)->name))
|
||||||
"AUTH %s", (*m)->name);
|
return -1;
|
||||||
/* wait for feedback */
|
|
||||||
nread = Curl_GetFTPResponse(conn->firstsocket,
|
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
|
||||||
conn->data->state.buffer, conn, NULL);
|
|
||||||
if(nread < 0)
|
if(nread < 0)
|
||||||
return /*CURLE_OPERATION_TIMEOUTED*/-1;
|
return -1;
|
||||||
if(/*ret != CONTINUE*/conn->data->state.buffer[0] != '3'){
|
|
||||||
if(/*code == 504*/strncmp(conn->data->state.buffer,"504",3) == 0) {
|
if(conn->data->state.buffer[0] != '3'){
|
||||||
|
switch(ftpcode) {
|
||||||
|
case 504:
|
||||||
infof(data,
|
infof(data,
|
||||||
"%s is not supported by the server.\n", (*m)->name);
|
"%s is not supported by the server.\n", (*m)->name);
|
||||||
}
|
break;
|
||||||
else if(/*code == 534*/strncmp(conn->data->state.buffer,"534",3) == 0) {
|
case 534:
|
||||||
infof(data, "%s rejected as security mechanism.\n", (*m)->name);
|
infof(data, "%s rejected as security mechanism.\n", (*m)->name);
|
||||||
}
|
break;
|
||||||
else if(/*ret == ERROR*/conn->data->state.buffer[0] == '5') {
|
default:
|
||||||
infof(data, "The server doesn't support the FTP "
|
if(conn->data->state.buffer[0] == '5') {
|
||||||
"security extensions.\n");
|
infof(data, "The server doesn't support the FTP "
|
||||||
return -1;
|
"security extensions.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (*(*m)->auth)(conn->app_data, /*host***/conn);
|
ret = (*(*m)->auth)(conn->app_data, conn);
|
||||||
|
|
||||||
if(ret == AUTH_CONTINUE)
|
if(ret == AUTH_CONTINUE)
|
||||||
continue;
|
continue;
|
||||||
@@ -551,6 +557,6 @@ Curl_sec_end(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
19
lib/sendf.c
19
lib/sendf.c
@@ -140,17 +140,20 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
if(data->set.errorbuffer)
|
if(data->set.errorbuffer && !data->state.errorbuf) {
|
||||||
vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
|
vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
|
||||||
|
data->state.errorbuf = TRUE; /* wrote error string */
|
||||||
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Curl_sendf() sends formated data to the server */
|
/* Curl_sendf() sends formated data to the server */
|
||||||
size_t Curl_sendf(int sockfd, struct connectdata *conn,
|
CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
size_t bytes_written;
|
size_t bytes_written;
|
||||||
|
CURLcode result;
|
||||||
char *s;
|
char *s;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -162,11 +165,11 @@ size_t Curl_sendf(int sockfd, struct connectdata *conn,
|
|||||||
fprintf(data->set.err, "> %s", s);
|
fprintf(data->set.err, "> %s", s);
|
||||||
|
|
||||||
/* Write the buffer to the socket */
|
/* Write the buffer to the socket */
|
||||||
Curl_write(conn, sockfd, s, strlen(s), &bytes_written);
|
result = Curl_write(conn, sockfd, s, strlen(s), &bytes_written);
|
||||||
|
|
||||||
free(s); /* free the output string */
|
free(s); /* free the output string */
|
||||||
|
|
||||||
return bytes_written;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -211,7 +214,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
*written = bytes_written;
|
*written = bytes_written;
|
||||||
return CURLE_OK;
|
return (bytes_written==len)?CURLE_OK:CURLE_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* client_write() sends data to the write callback(s)
|
/* client_write() sends data to the write callback(s)
|
||||||
@@ -296,6 +299,6 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
size_t Curl_sendf(int fd, struct connectdata *, const char *fmt, ...);
|
CURLcode Curl_sendf(int fd, struct connectdata *, const char *fmt, ...);
|
||||||
void Curl_infof(struct SessionHandle *, const char *fmt, ...);
|
void Curl_infof(struct SessionHandle *, const char *fmt, ...);
|
||||||
void Curl_failf(struct SessionHandle *, const char *fmt, ...);
|
void Curl_failf(struct SessionHandle *, const char *fmt, ...);
|
||||||
|
|
||||||
|
19
lib/setup.h
19
lib/setup.h
@@ -125,8 +125,8 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
#define sclose(x) close(x)
|
#define sclose(x) close(x)
|
||||||
#define sread(x,y,z) read(x,y,z)
|
#define sread(x,y,z) recv(x,y,z,0)
|
||||||
#define swrite(x,y,z) write(x,y,z)
|
#define swrite(x,y,z) send(x,y,z,0)
|
||||||
#define myalarm(x) alarm(x)
|
#define myalarm(x) alarm(x)
|
||||||
|
|
||||||
#define PATH_CHAR ":"
|
#define PATH_CHAR ":"
|
||||||
@@ -144,4 +144,19 @@ int fileno( FILE *stream);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_addrinfo MUST be used for name resolving information.
|
||||||
|
* Information regarding a single IP witin a Curl_addrinfo MUST be stored in
|
||||||
|
* a Curl_ipconnect struct.
|
||||||
|
*/
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
typedef struct addrinfo Curl_addrinfo;
|
||||||
|
typedef struct addrinfo Curl_ipconnect;
|
||||||
|
#else
|
||||||
|
typedef struct hostent Curl_addrinfo;
|
||||||
|
typedef struct in_addr Curl_ipconnect;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __CONFIG_H */
|
#endif /* __CONFIG_H */
|
||||||
|
@@ -51,7 +51,8 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
|
|||||||
for "low speed time" seconds we consider that enough reason
|
for "low speed time" seconds we consider that enough reason
|
||||||
to abort the download. */
|
to abort the download. */
|
||||||
|
|
||||||
if( Curl_tvdiff(now, data->state.keeps_speed) > data->set.low_speed_time) {
|
if( (Curl_tvdiff(now, data->state.keeps_speed)/1000) >
|
||||||
|
data->set.low_speed_time) {
|
||||||
/* we have been this slow for long enough, now die */
|
/* we have been this slow for long enough, now die */
|
||||||
failf(data,
|
failf(data,
|
||||||
"Operation too slow. "
|
"Operation too slow. "
|
||||||
@@ -72,6 +73,6 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -725,6 +725,6 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -112,6 +112,6 @@ size_t Curl_strlcat(char *dst, const char *src, size_t siz)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -69,6 +69,6 @@ Curl_strtok_r(char *ptr, const char *sep, char **end)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -1206,6 +1206,6 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -65,9 +65,14 @@ struct timeval Curl_tvnow (void)
|
|||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Curl_tvdiff (struct timeval t1, struct timeval t2)
|
/*
|
||||||
|
* Make sure that the first argument is the more recent time, as otherwise
|
||||||
|
* we'll get a weird negative time-diff back...
|
||||||
|
*/
|
||||||
|
long Curl_tvdiff (struct timeval t1, struct timeval t2)
|
||||||
{
|
{
|
||||||
return (double)(t1.tv_sec - t2.tv_sec) + ((t1.tv_usec-t2.tv_usec)/1000000.0);
|
return (t1.tv_sec*1000 + t1.tv_usec/1000)-
|
||||||
|
(t2.tv_sec*1000 + t2.tv_usec/1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
long Curl_tvlong (struct timeval t1)
|
long Curl_tvlong (struct timeval t1)
|
||||||
@@ -79,6 +84,6 @@ long Curl_tvlong (struct timeval t1)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -43,7 +43,10 @@ struct timeval {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct timeval Curl_tvnow ();
|
struct timeval Curl_tvnow ();
|
||||||
double Curl_tvdiff (struct timeval t1, struct timeval t2);
|
|
||||||
|
/* the diff is from now on returned in number of milliseconds! */
|
||||||
|
long Curl_tvdiff (struct timeval t1, struct timeval t2);
|
||||||
|
|
||||||
long Curl_tvlong (struct timeval t1);
|
long Curl_tvlong (struct timeval t1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -220,8 +220,6 @@ Transfer(struct connectdata *c_conn)
|
|||||||
|
|
||||||
hbufp = data->state.headerbuff;
|
hbufp = data->state.headerbuff;
|
||||||
|
|
||||||
myalarm (0); /* switch off the alarm-style timeout */
|
|
||||||
|
|
||||||
now = Curl_tvnow();
|
now = Curl_tvnow();
|
||||||
start = now;
|
start = now;
|
||||||
|
|
||||||
@@ -452,12 +450,14 @@ Transfer(struct connectdata *c_conn)
|
|||||||
if (data->set.http_include_header)
|
if (data->set.http_include_header)
|
||||||
writetype |= CLIENTWRITE_BODY;
|
writetype |= CLIENTWRITE_BODY;
|
||||||
|
|
||||||
urg = Curl_client_write(data, writetype, data->state.headerbuff,
|
urg = Curl_client_write(data, writetype,
|
||||||
|
data->state.headerbuff,
|
||||||
p - data->state.headerbuff);
|
p - data->state.headerbuff);
|
||||||
if(urg)
|
if(urg)
|
||||||
return urg;
|
return urg;
|
||||||
|
|
||||||
data->info.header_size += p - data->state.headerbuff;
|
data->info.header_size += p - data->state.headerbuff;
|
||||||
|
conn->headerbytecount += p - data->state.headerbuff;
|
||||||
|
|
||||||
if(!header) {
|
if(!header) {
|
||||||
/*
|
/*
|
||||||
@@ -520,13 +520,8 @@ Transfer(struct connectdata *c_conn)
|
|||||||
data->info.httpversion = httpversion;
|
data->info.httpversion = httpversion;
|
||||||
|
|
||||||
/* 404 -> URL not found! */
|
/* 404 -> URL not found! */
|
||||||
if (
|
if (data->set.http_fail_on_error &&
|
||||||
( ((data->set.http_follow_location) &&
|
(httpcode >= 400)) {
|
||||||
(httpcode >= 400))
|
|
||||||
||
|
|
||||||
(!data->set.http_follow_location &&
|
|
||||||
(httpcode >= 300)))
|
|
||||||
&& (data->set.http_fail_on_error)) {
|
|
||||||
/* If we have been told to fail hard on HTTP-errors,
|
/* If we have been told to fail hard on HTTP-errors,
|
||||||
here is the check for that: */
|
here is the check for that: */
|
||||||
/* serious error, go home! */
|
/* serious error, go home! */
|
||||||
@@ -620,14 +615,14 @@ Transfer(struct connectdata *c_conn)
|
|||||||
}
|
}
|
||||||
else if(data->cookies &&
|
else if(data->cookies &&
|
||||||
strnequal("Set-Cookie:", p, 11)) {
|
strnequal("Set-Cookie:", p, 11)) {
|
||||||
Curl_cookie_add(data->cookies, TRUE, &p[12]);
|
Curl_cookie_add(data->cookies, TRUE, &p[12], conn->name);
|
||||||
}
|
}
|
||||||
else if(strnequal("Last-Modified:", p,
|
else if(strnequal("Last-Modified:", p,
|
||||||
strlen("Last-Modified:")) &&
|
strlen("Last-Modified:")) &&
|
||||||
(data->set.timecondition || data->set.get_filetime) ) {
|
(data->set.timecondition || data->set.get_filetime) ) {
|
||||||
time_t secs=time(NULL);
|
time_t secs=time(NULL);
|
||||||
timeofdoc = curl_getdate(p+strlen("Last-Modified:"), &secs);
|
timeofdoc = curl_getdate(p+strlen("Last-Modified:"), &secs);
|
||||||
if(data->set.get_filetime)
|
if(data->set.get_filetime>=0)
|
||||||
data->info.filetime = timeofdoc;
|
data->info.filetime = timeofdoc;
|
||||||
}
|
}
|
||||||
else if ((httpcode >= 300 && httpcode < 400) &&
|
else if ((httpcode >= 300 && httpcode < 400) &&
|
||||||
@@ -844,6 +839,12 @@ Transfer(struct connectdata *c_conn)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update read/write counters */
|
||||||
|
if(conn->bytecountp)
|
||||||
|
*conn->bytecountp = bytecount; /* read count */
|
||||||
|
if(conn->writebytecountp)
|
||||||
|
*conn->writebytecountp = writebytecount; /* write count */
|
||||||
|
|
||||||
now = Curl_tvnow();
|
now = Curl_tvnow();
|
||||||
if(Curl_pgrsUpdate(conn))
|
if(Curl_pgrsUpdate(conn))
|
||||||
urg = CURLE_ABORTED_BY_CALLBACK;
|
urg = CURLE_ABORTED_BY_CALLBACK;
|
||||||
@@ -861,11 +862,13 @@ Transfer(struct connectdata *c_conn)
|
|||||||
conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE);
|
conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->set.timeout && (Curl_tvdiff (now, start) > data->set.timeout)) {
|
if (data->set.timeout &&
|
||||||
|
((Curl_tvdiff(now, start)/1000) >= data->set.timeout)) {
|
||||||
failf (data, "Operation timed out with %d out of %d bytes received",
|
failf (data, "Operation timed out with %d out of %d bytes received",
|
||||||
bytecount, conn->size);
|
bytecount, conn->size);
|
||||||
return CURLE_OPERATION_TIMEOUTED;
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,11 +891,6 @@ Transfer(struct connectdata *c_conn)
|
|||||||
if(Curl_pgrsUpdate(conn))
|
if(Curl_pgrsUpdate(conn))
|
||||||
return CURLE_ABORTED_BY_CALLBACK;
|
return CURLE_ABORTED_BY_CALLBACK;
|
||||||
|
|
||||||
if(conn->bytecountp)
|
|
||||||
*conn->bytecountp = bytecount; /* read count */
|
|
||||||
if(conn->writebytecountp)
|
|
||||||
*conn->writebytecountp = writebytecount; /* write count */
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,6 +914,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
|||||||
|
|
||||||
data->set.followlocation=0; /* reset the location-follow counter */
|
data->set.followlocation=0; /* reset the location-follow counter */
|
||||||
data->state.this_is_a_follow = FALSE; /* reset this */
|
data->state.this_is_a_follow = FALSE; /* reset this */
|
||||||
|
data->state.errorbuf = FALSE; /* no error has occurred */
|
||||||
|
|
||||||
Curl_initinfo(data); /* reset session-specific information "variables" */
|
Curl_initinfo(data); /* reset session-specific information "variables" */
|
||||||
|
|
||||||
@@ -926,7 +925,31 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
|||||||
res = Curl_connect(data, &conn, port);
|
res = Curl_connect(data, &conn, port);
|
||||||
if(res == CURLE_OK) {
|
if(res == CURLE_OK) {
|
||||||
res = Curl_do(conn);
|
res = Curl_do(conn);
|
||||||
|
|
||||||
|
if((CURLE_WRITE_ERROR == res) && conn->bits.reuse) {
|
||||||
|
/* This was a re-use of a connection and we got a write error in the
|
||||||
|
* DO-phase. Then we DISCONNECT this connection and have another
|
||||||
|
* attempt to CONNECT and then DO again! The retry cannot possibly
|
||||||
|
* find another connection to re-use, since we only keep one possible
|
||||||
|
* connection for each.
|
||||||
|
*/
|
||||||
|
|
||||||
|
infof(data, "The re-used connection seems dead, get a new one\n");
|
||||||
|
|
||||||
|
conn->bits.close = TRUE; /* enforce close of this connetion */
|
||||||
|
res = Curl_done(conn); /* we are so done with this */
|
||||||
|
if(CURLE_OK == res) {
|
||||||
|
/* Now, redo the connect */
|
||||||
|
res = Curl_connect(data, &conn, port);
|
||||||
|
if(CURLE_OK == res)
|
||||||
|
/* ... finally back to actually retry the DO phase */
|
||||||
|
res = Curl_do(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(res == CURLE_OK) {
|
if(res == CURLE_OK) {
|
||||||
|
CURLcode res2; /* just a local extra result container */
|
||||||
|
|
||||||
if(conn->protocol&PROT_FTPS)
|
if(conn->protocol&PROT_FTPS)
|
||||||
/* FTPS, disable ssl while transfering data */
|
/* FTPS, disable ssl while transfering data */
|
||||||
conn->ssl.use = FALSE;
|
conn->ssl.use = FALSE;
|
||||||
@@ -935,15 +958,24 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
|||||||
/* FTPS, enable ssl again after havving transferred data */
|
/* FTPS, enable ssl again after havving transferred data */
|
||||||
conn->ssl.use = TRUE;
|
conn->ssl.use = TRUE;
|
||||||
|
|
||||||
if(res == CURLE_OK) {
|
if(res == CURLE_OK)
|
||||||
/*
|
/*
|
||||||
* We must duplicate the new URL here as the connection data
|
* We must duplicate the new URL here as the connection data
|
||||||
* may be free()ed in the Curl_done() function.
|
* may be free()ed in the Curl_done() function.
|
||||||
*/
|
*/
|
||||||
newurl = conn->newurl?strdup(conn->newurl):NULL;
|
newurl = conn->newurl?strdup(conn->newurl):NULL;
|
||||||
|
else
|
||||||
|
/* The transfer phase returned error, we mark the connection to get
|
||||||
|
* closed to prevent being re-used. This is becasue we can't
|
||||||
|
* possibly know if the connection is in a good shape or not now. */
|
||||||
|
conn->bits.close = TRUE;
|
||||||
|
|
||||||
res = Curl_done(conn);
|
/* Always run Curl_done(), even if some of the previous calls
|
||||||
}
|
failed, but return the previous (original) error code */
|
||||||
|
res2 = Curl_done(conn);
|
||||||
|
|
||||||
|
if(CURLE_OK == res)
|
||||||
|
res = res2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -986,7 +1018,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
|||||||
data->change.referer_alloc = TRUE; /* yes, free this later */
|
data->change.referer_alloc = TRUE; /* yes, free this later */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(2 != sscanf(newurl, "%15[^:]://%c", prot, &letter)) {
|
if(2 != sscanf(newurl, "%15[^?&/:]://%c", prot, &letter)) {
|
||||||
/***
|
/***
|
||||||
*DANG* this is an RFC 2068 violation. The URL is supposed
|
*DANG* this is an RFC 2068 violation. The URL is supposed
|
||||||
to be absolute and this doesn't seem to be that!
|
to be absolute and this doesn't seem to be that!
|
||||||
@@ -1127,7 +1159,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
|||||||
if(newurl)
|
if(newurl)
|
||||||
free(newurl);
|
free(newurl);
|
||||||
|
|
||||||
/* make sure the alarm is switched off! */
|
/* make absolutely sure the alarm is switched off! */
|
||||||
if(data->set.timeout || data->set.connecttimeout)
|
if(data->set.timeout || data->set.connecttimeout)
|
||||||
myalarm(0);
|
myalarm(0);
|
||||||
|
|
||||||
@@ -1166,6 +1198,6 @@ Curl_Transfer(struct connectdata *c_conn, /* connection data */
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
568
lib/url.c
568
lib/url.c
@@ -107,6 +107,7 @@
|
|||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "ldap.h"
|
#include "ldap.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
|
#include "connect.h"
|
||||||
|
|
||||||
#include <curl/types.h>
|
#include <curl/types.h>
|
||||||
|
|
||||||
@@ -205,84 +206,89 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
|||||||
|
|
||||||
/* Very simple start-up: alloc the struct, init it with zeroes and return */
|
/* Very simple start-up: alloc the struct, init it with zeroes and return */
|
||||||
data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle));
|
data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle));
|
||||||
if(data) {
|
if(!data)
|
||||||
memset(data, 0, sizeof(struct SessionHandle));
|
/* this is a very serious error */
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(struct SessionHandle));
|
||||||
|
|
||||||
/* We do some initial setup here, all those fields that can't be just 0 */
|
/* We do some initial setup here, all those fields that can't be just 0 */
|
||||||
|
|
||||||
data->state.headerbuff=(char*)malloc(HEADERSIZE);
|
data->state.headerbuff=(char*)malloc(HEADERSIZE);
|
||||||
if(!data->state.headerbuff) {
|
if(!data->state.headerbuff) {
|
||||||
free(data); /* free the memory again */
|
free(data); /* free the memory again */
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
|
||||||
|
|
||||||
data->state.headersize=HEADERSIZE;
|
|
||||||
|
|
||||||
data->set.out = stdout; /* default output to stdout */
|
|
||||||
data->set.in = stdin; /* default input from stdin */
|
|
||||||
data->set.err = stderr; /* default stderr to stderr */
|
|
||||||
|
|
||||||
/* use fwrite as default function to store output */
|
|
||||||
data->set.fwrite = (curl_write_callback)fwrite;
|
|
||||||
|
|
||||||
/* use fread as default function to read input */
|
|
||||||
data->set.fread = (curl_read_callback)fread;
|
|
||||||
|
|
||||||
/* set the default passwd function */
|
|
||||||
data->set.fpasswd = my_getpass;
|
|
||||||
|
|
||||||
data->set.infilesize = -1; /* we don't know any size */
|
|
||||||
|
|
||||||
data->state.current_speed = -1; /* init to negative == impossible */
|
|
||||||
|
|
||||||
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
|
|
||||||
|
|
||||||
/* make libcurl quiet by default: */
|
|
||||||
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
|
|
||||||
data->progress.flags |= PGRS_HIDE;
|
|
||||||
|
|
||||||
/* Set the default size of the SSL session ID cache */
|
|
||||||
data->set.ssl.numsessions = 5;
|
|
||||||
|
|
||||||
/* create an array with connection data struct pointers */
|
|
||||||
data->state.numconnects = 5; /* hard-coded right now */
|
|
||||||
data->state.connects = (struct connectdata **)
|
|
||||||
malloc(sizeof(struct connectdata *) * data->state.numconnects);
|
|
||||||
|
|
||||||
if(!data->state.connects) {
|
|
||||||
free(data);
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(data->state.connects, 0,
|
|
||||||
sizeof(struct connectdata *)*data->state.numconnects);
|
|
||||||
|
|
||||||
*curl = data;
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Set signal handler
|
|
||||||
*************************************************************/
|
|
||||||
#ifdef HAVE_SIGACTION
|
|
||||||
sigaction(SIGALRM, NULL, &sigact);
|
|
||||||
sigact.sa_handler = alarmfunc;
|
|
||||||
#ifdef SA_RESTART
|
|
||||||
/* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
|
|
||||||
sigact.sa_flags &= ~SA_RESTART;
|
|
||||||
#endif
|
|
||||||
sigaction(SIGALRM, &sigact, NULL);
|
|
||||||
#else
|
|
||||||
/* no sigaction(), revert to the much lamer signal() */
|
|
||||||
#ifdef HAVE_SIGNAL
|
|
||||||
signal(SIGALRM, alarmfunc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is a very serious error */
|
data->state.headersize=HEADERSIZE;
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
data->set.out = stdout; /* default output to stdout */
|
||||||
|
data->set.in = stdin; /* default input from stdin */
|
||||||
|
data->set.err = stderr; /* default stderr to stderr */
|
||||||
|
|
||||||
|
/* use fwrite as default function to store output */
|
||||||
|
data->set.fwrite = (curl_write_callback)fwrite;
|
||||||
|
|
||||||
|
/* use fread as default function to read input */
|
||||||
|
data->set.fread = (curl_read_callback)fread;
|
||||||
|
|
||||||
|
/* set the default passwd function */
|
||||||
|
data->set.fpasswd = my_getpass;
|
||||||
|
|
||||||
|
data->set.infilesize = -1; /* we don't know any size */
|
||||||
|
|
||||||
|
data->state.current_speed = -1; /* init to negative == impossible */
|
||||||
|
|
||||||
|
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
|
||||||
|
|
||||||
|
/* make libcurl quiet by default: */
|
||||||
|
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
|
||||||
|
data->progress.flags |= PGRS_HIDE;
|
||||||
|
|
||||||
|
/* Set the default size of the SSL session ID cache */
|
||||||
|
data->set.ssl.numsessions = 5;
|
||||||
|
|
||||||
|
/* create an array with connection data struct pointers */
|
||||||
|
data->state.numconnects = 5; /* hard-coded right now */
|
||||||
|
data->state.connects = (struct connectdata **)
|
||||||
|
malloc(sizeof(struct connectdata *) * data->state.numconnects);
|
||||||
|
|
||||||
|
if(!data->state.connects) {
|
||||||
|
free(data);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(data->state.connects, 0,
|
||||||
|
sizeof(struct connectdata *)*data->state.numconnects);
|
||||||
|
|
||||||
|
*curl = data;
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Set signal handler to catch SIGALRM
|
||||||
|
*************************************************************/
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
|
sigaction(SIGALRM, NULL, &sigact);
|
||||||
|
sigact.sa_handler = alarmfunc;
|
||||||
|
#ifdef SA_RESTART
|
||||||
|
/* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
|
||||||
|
sigact.sa_flags &= ~SA_RESTART;
|
||||||
|
#endif
|
||||||
|
sigaction(SIGALRM, &sigact, NULL);
|
||||||
|
#else
|
||||||
|
/* no sigaction(), revert to the much lamer signal() */
|
||||||
|
#ifdef HAVE_SIGNAL
|
||||||
|
signal(SIGALRM, alarmfunc);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Tell signal handler to ignore SIGPIPE
|
||||||
|
*************************************************************/
|
||||||
|
#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
|
||||||
|
(void) signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||||
@@ -438,6 +444,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
*/
|
*/
|
||||||
data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
|
data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
|
||||||
break;
|
break;
|
||||||
|
case CURLOPT_HTTP_VERSION:
|
||||||
|
/*
|
||||||
|
* This sets a requested HTTP version to be used. The value is one of
|
||||||
|
* the listed enums in curl/curl.h.
|
||||||
|
*/
|
||||||
|
data->set.httpversion = va_arg(param, long);
|
||||||
|
break;
|
||||||
case CURLOPT_TRANSFERTEXT:
|
case CURLOPT_TRANSFERTEXT:
|
||||||
/*
|
/*
|
||||||
* This option was previously named 'FTPASCII'. Renamed to work with
|
* This option was previously named 'FTPASCII'. Renamed to work with
|
||||||
@@ -455,15 +468,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
if(va_arg(param, long))
|
if(va_arg(param, long))
|
||||||
data->set.httpreq = HTTPREQ_PUT;
|
data->set.httpreq = HTTPREQ_PUT;
|
||||||
break;
|
break;
|
||||||
#if 0
|
|
||||||
/* obsolete stuff, kept here a while for informational purposes */
|
|
||||||
case CURLOPT_MUTE:
|
|
||||||
/*
|
|
||||||
* Stay absolutely quiet.
|
|
||||||
*/
|
|
||||||
data->set.mute = va_arg(param, long)?TRUE:FALSE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case CURLOPT_TIMECONDITION:
|
case CURLOPT_TIMECONDITION:
|
||||||
/*
|
/*
|
||||||
* Set HTTP time condition. This must be one of the defines in the
|
* Set HTTP time condition. This must be one of the defines in the
|
||||||
@@ -499,7 +503,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
/*
|
/*
|
||||||
* Set cookie file name to dump all cookies to when we're done.
|
* Set cookie file name to dump all cookies to when we're done.
|
||||||
*/
|
*/
|
||||||
data->set.cookiejar = cookiefile = (char *)va_arg(param, void *);
|
data->set.cookiejar = (char *)va_arg(param, void *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Activate the cookie parser. This may or may not already
|
||||||
|
* have been made.
|
||||||
|
*/
|
||||||
|
data->cookies = Curl_cookie_init(NULL, data->cookies);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_WRITEHEADER:
|
case CURLOPT_WRITEHEADER:
|
||||||
/*
|
/*
|
||||||
@@ -867,7 +877,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
|||||||
|
|
||||||
if(-1 != conn->connectindex) {
|
if(-1 != conn->connectindex) {
|
||||||
/* unlink ourselves! */
|
/* unlink ourselves! */
|
||||||
infof(conn->data, "Closing live connection (#%d)\n", conn->connectindex);
|
infof(conn->data, "Closing connection #%d\n", conn->connectindex);
|
||||||
conn->data->state.connects[conn->connectindex] = NULL;
|
conn->data->state.connects[conn->connectindex] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,13 +888,8 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
|||||||
if(conn->proto.generic)
|
if(conn->proto.generic)
|
||||||
free(conn->proto.generic);
|
free(conn->proto.generic);
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
if(conn->hp) /* host name info */
|
|
||||||
freeaddrinfo(conn->hp);
|
|
||||||
#else
|
|
||||||
if(conn->hostent_buf) /* host name info */
|
if(conn->hostent_buf) /* host name info */
|
||||||
free(conn->hostent_buf);
|
Curl_freeaddrinfo(conn->hostent_buf);
|
||||||
#endif
|
|
||||||
|
|
||||||
if(conn->newurl)
|
if(conn->newurl)
|
||||||
free(conn->newurl);
|
free(conn->newurl);
|
||||||
@@ -944,9 +949,9 @@ static bool SocketIsDead(int sock)
|
|||||||
to.tv_usec = 1;
|
to.tv_usec = 1;
|
||||||
|
|
||||||
sval = select(sock + 1, &check_set, 0, 0, &to);
|
sval = select(sock + 1, &check_set, 0, 0, &to);
|
||||||
if(sval == 0)
|
if(sval == 0)
|
||||||
/* timeout */
|
/* timeout */
|
||||||
ret_val = FALSE;
|
ret_val = FALSE;
|
||||||
|
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
@@ -991,10 +996,20 @@ ConnectionExists(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
dead = SocketIsDead(check->firstsocket);
|
dead = SocketIsDead(check->firstsocket);
|
||||||
if(dead) {
|
if(dead) {
|
||||||
|
/*
|
||||||
|
* Even though the connection seems to have passed away, we could
|
||||||
|
* still make an effort to get the name information, as we intend to
|
||||||
|
* connect to the same host again.
|
||||||
|
*
|
||||||
|
* This is now subject to discussion. What do you think?
|
||||||
|
*/
|
||||||
infof(data, "Connection %d seems to be dead!\n", i);
|
infof(data, "Connection %d seems to be dead!\n", i);
|
||||||
Curl_disconnect(check); /* disconnect resources */
|
Curl_disconnect(check); /* disconnect resources */
|
||||||
data->state.connects[i]=NULL; /* nothing here */
|
data->state.connects[i]=NULL; /* nothing here */
|
||||||
continue; /* try another one now */
|
|
||||||
|
/* There's no need to continue search, because we only store
|
||||||
|
one connection for each unique set of identifiers */
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*usethis = check;
|
*usethis = check;
|
||||||
@@ -1050,14 +1065,14 @@ ConnectionKillOne(struct SessionHandle *data)
|
|||||||
* Set higher score for the age passed since the connection
|
* Set higher score for the age passed since the connection
|
||||||
* was used.
|
* was used.
|
||||||
*/
|
*/
|
||||||
score = Curl_tvlong(now) - Curl_tvlong(conn->now);
|
score = Curl_tvdiff(now, conn->now);
|
||||||
break;
|
break;
|
||||||
case CURLCLOSEPOLICY_OLDEST:
|
case CURLCLOSEPOLICY_OLDEST:
|
||||||
/*
|
/*
|
||||||
* Set higher score for the age passed since the connection
|
* Set higher score for the age passed since the connection
|
||||||
* was created.
|
* was created.
|
||||||
*/
|
*/
|
||||||
score = Curl_tvlong(now) - Curl_tvlong(conn->created);
|
score = Curl_tvdiff(now, conn->created);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,255 +1127,40 @@ ConnectionStore(struct SessionHandle *data,
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode ConnectPlease(struct SessionHandle *data,
|
static CURLcode ConnectPlease(struct connectdata *conn)
|
||||||
struct connectdata *conn)
|
|
||||||
{
|
{
|
||||||
#if defined(WIN32)
|
CURLcode result;
|
||||||
unsigned long nonblock = 0;
|
Curl_ipconnect *addr;
|
||||||
fd_set connectfd;
|
|
||||||
struct timeval conntimeout;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ENABLE_IPV6
|
|
||||||
conn->firstsocket = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
|
|
||||||
memcpy((char *)&(conn->serv_addr.sin_addr),
|
|
||||||
conn->hp->h_addr, conn->hp->h_length);
|
|
||||||
conn->serv_addr.sin_family = conn->hp->h_addrtype;
|
|
||||||
conn->serv_addr.sin_port = htons(conn->port);
|
|
||||||
#else
|
|
||||||
/* IPv6-style */
|
|
||||||
struct addrinfo *ai;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(WIN32)||defined(__CYGWIN32__)
|
|
||||||
/* We don't generally like checking for OS-versions, we should make this
|
|
||||||
HAVE_XXXX based, although at the moment I don't have a decent test for
|
|
||||||
this! */
|
|
||||||
|
|
||||||
#ifdef HAVE_INET_NTOA
|
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
|
||||||
#define INADDR_NONE (unsigned long) ~0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ENABLE_IPV6
|
|
||||||
/*************************************************************
|
|
||||||
* Select device to bind socket to
|
|
||||||
*************************************************************/
|
|
||||||
if (data->set.device && (strlen(data->set.device)<255)) {
|
|
||||||
struct sockaddr_in sa;
|
|
||||||
struct hostent *h=NULL;
|
|
||||||
char *hostdataptr=NULL;
|
|
||||||
size_t size;
|
|
||||||
char myhost[256] = "";
|
|
||||||
unsigned long in;
|
|
||||||
|
|
||||||
if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
|
|
||||||
h = Curl_gethost(data, myhost, &hostdataptr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(strlen(data->set.device)>1) {
|
|
||||||
h = Curl_gethost(data, data->set.device, &hostdataptr);
|
|
||||||
}
|
|
||||||
if(h) {
|
|
||||||
/* we know data->set.device is shorter than the myhost array */
|
|
||||||
strcpy(myhost, data->set.device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(! *myhost) {
|
|
||||||
/* need to fix this
|
|
||||||
h=Curl_gethost(data,
|
|
||||||
getmyhost(*myhost,sizeof(myhost)),
|
|
||||||
hostent_buf,
|
|
||||||
sizeof(hostent_buf));
|
|
||||||
*/
|
|
||||||
printf("in here\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
infof(data, "We connect from %s\n", myhost);
|
|
||||||
|
|
||||||
if ( (in=inet_addr(myhost)) != INADDR_NONE ) {
|
|
||||||
|
|
||||||
if ( h ) {
|
|
||||||
memset((char *)&sa, 0, sizeof(sa));
|
|
||||||
memcpy((char *)&sa.sin_addr,
|
|
||||||
h->h_addr,
|
|
||||||
h->h_length);
|
|
||||||
sa.sin_family = AF_INET;
|
|
||||||
sa.sin_addr.s_addr = in;
|
|
||||||
sa.sin_port = 0; /* get any port */
|
|
||||||
|
|
||||||
if( bind(conn->firstsocket, (struct sockaddr *)&sa, sizeof(sa)) >= 0) {
|
|
||||||
/* we succeeded to bind */
|
|
||||||
struct sockaddr_in add;
|
|
||||||
|
|
||||||
size = sizeof(add);
|
|
||||||
if(getsockname(conn->firstsocket, (struct sockaddr *) &add,
|
|
||||||
(socklen_t *)&size)<0) {
|
|
||||||
failf(data, "getsockname() failed");
|
|
||||||
return CURLE_HTTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch(errno) {
|
|
||||||
case EBADF:
|
|
||||||
failf(data, "Invalid descriptor: %d", errno);
|
|
||||||
break;
|
|
||||||
case EINVAL:
|
|
||||||
failf(data, "Invalid request: %d", errno);
|
|
||||||
break;
|
|
||||||
case EACCES:
|
|
||||||
failf(data, "Address is protected, user not superuser: %d", errno);
|
|
||||||
break;
|
|
||||||
case ENOTSOCK:
|
|
||||||
failf(data,
|
|
||||||
"Argument is a descriptor for a file, not a socket: %d",
|
|
||||||
errno);
|
|
||||||
break;
|
|
||||||
case EFAULT:
|
|
||||||
failf(data, "Inaccessable memory error: %d", errno);
|
|
||||||
break;
|
|
||||||
case ENAMETOOLONG:
|
|
||||||
failf(data, "Address too long: %d", errno);
|
|
||||||
break;
|
|
||||||
case ENOMEM:
|
|
||||||
failf(data, "Insufficient kernel memory was available: %d", errno);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
failf(data,"errno %d\n");
|
|
||||||
} /* end of switch */
|
|
||||||
|
|
||||||
return CURLE_HTTP_PORT_FAILED;
|
|
||||||
} /* end of else */
|
|
||||||
|
|
||||||
} /* end of if h */
|
|
||||||
else {
|
|
||||||
failf(data,"could't find my own IP address (%s)", myhost);
|
|
||||||
return CURLE_HTTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
} /* end of inet_addr */
|
|
||||||
|
|
||||||
else {
|
|
||||||
failf(data, "could't find my own IP address (%s)", myhost);
|
|
||||||
return CURLE_HTTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hostdataptr)
|
|
||||||
free(hostdataptr); /* allocated by Curl_gethost() */
|
|
||||||
|
|
||||||
} /* end of device selection support */
|
|
||||||
#endif /* end of HAVE_INET_NTOA */
|
|
||||||
#endif /* end of not WIN32 */
|
|
||||||
#endif /*ENABLE_IPV6*/
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Connect to server/proxy
|
* Connect to server/proxy
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
result= Curl_connecthost(conn,
|
||||||
|
conn->hostaddr,
|
||||||
|
conn->port,
|
||||||
|
&conn->firstsocket,
|
||||||
|
&addr);
|
||||||
|
if(CURLE_OK == result) {
|
||||||
|
/* All is cool, then we store the current information from the hostaddr
|
||||||
|
struct to the serv_addr, as it might be needed later. The address
|
||||||
|
returned from the function above is crucial here. */
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
conn->firstsocket = -1;
|
conn->serv_addr = addr;
|
||||||
for (ai = conn->hp; ai; ai = ai->ai_next) {
|
|
||||||
conn->firstsocket = socket(ai->ai_family,
|
|
||||||
ai->ai_socktype,
|
|
||||||
ai->ai_protocol);
|
|
||||||
if (conn->firstsocket < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (connect(conn->firstsocket, ai->ai_addr, ai->ai_addrlen) < 0) {
|
|
||||||
sclose(conn->firstsocket);
|
|
||||||
conn->firstsocket = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
conn->ai = ai;
|
|
||||||
if (conn->firstsocket < 0) {
|
|
||||||
failf(data, strerror(errno));
|
|
||||||
return CURLE_COULDNT_CONNECT;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
/* non-zero nonblock value sets socket as nonblocking under Win32 */
|
memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
|
||||||
#if defined(WIN32)
|
memcpy((char *)&(conn->serv_addr.sin_addr),
|
||||||
FD_ZERO (&connectfd);
|
(struct in_addr *)addr, sizeof(struct in_addr));
|
||||||
FD_SET(conn->firstsocket, &connectfd);
|
conn->serv_addr.sin_family = conn->hostaddr->h_addrtype;
|
||||||
if (conn->data->set.connecttimeout > 0) {
|
conn->serv_addr.sin_port = htons(conn->port);
|
||||||
nonblock = 1;
|
#endif
|
||||||
}
|
}
|
||||||
ioctlsocket(conn->firstsocket, FIONBIO, &nonblock);
|
|
||||||
#endif
|
|
||||||
if (connect(conn->firstsocket,
|
|
||||||
(struct sockaddr *) &(conn->serv_addr),
|
|
||||||
sizeof(conn->serv_addr)
|
|
||||||
) < 0) {
|
|
||||||
#if defined(WIN32)
|
|
||||||
conntimeout.tv_sec = conn->data->set.connecttimeout;
|
|
||||||
conntimeout.tv_usec = 0;
|
|
||||||
if(-1 != select (conn->firstsocket + 1, NULL, &connectfd, NULL, &conntimeout)) {
|
|
||||||
if (FD_ISSET(conn->firstsocket, &connectfd)) {
|
|
||||||
/* shut off non-blocking again */
|
|
||||||
nonblock = 0;
|
|
||||||
ioctlsocket(conn->firstsocket, FIONBIO, &nonblock);
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
errno = EINTR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
switch(errno) {
|
|
||||||
#ifdef ECONNREFUSED
|
|
||||||
/* this should be made nicer */
|
|
||||||
case ECONNREFUSED:
|
|
||||||
failf(data, "Connection refused");
|
|
||||||
break;
|
|
||||||
case EFAULT:
|
|
||||||
failf(data, "Invalid socket address: %d",errno);
|
|
||||||
break;
|
|
||||||
case EISCONN:
|
|
||||||
failf(data, "Socket already connected: %d",errno);
|
|
||||||
break;
|
|
||||||
case ETIMEDOUT:
|
|
||||||
failf(data, "Timeout while accepting connection, server busy: %d",errno);
|
|
||||||
break;
|
|
||||||
case ENETUNREACH:
|
|
||||||
failf(data, "Network is unreachable: %d",errno);
|
|
||||||
break;
|
|
||||||
case EADDRINUSE:
|
|
||||||
failf(data, "Local address already in use: %d",errno);
|
|
||||||
break;
|
|
||||||
case EINPROGRESS:
|
|
||||||
failf(data, "Socket is nonblocking and connection can not be completed immediately: %d",errno);
|
|
||||||
break;
|
|
||||||
case EALREADY:
|
|
||||||
failf(data, "Socket is nonblocking and a previous connection attempt not completed: %d",errno);
|
|
||||||
break;
|
|
||||||
case EAGAIN:
|
|
||||||
failf(data, "No more free local ports: %d",errno);
|
|
||||||
break;
|
|
||||||
case EACCES:
|
|
||||||
case EPERM:
|
|
||||||
failf(data, "Attempt to connect to broadcast address without socket broadcast flag or local firewall rule violated: %d",errno);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case EINTR:
|
|
||||||
failf(data, "Connection timed out");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
failf(data, "Can't connect to server: %d", errno);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return CURLE_COULDNT_CONNECT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode Connect(struct SessionHandle *data,
|
static CURLcode CreateConnection(struct SessionHandle *data,
|
||||||
struct connectdata **in_connect,
|
struct connectdata **in_connect,
|
||||||
bool allow_port) /* allow data->set.use_port ? */
|
bool allow_port) /* allow set.use_port? */
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char *buf;
|
char *buf;
|
||||||
@@ -1490,14 +1290,14 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
strcpy(conn->path, "/");
|
strcpy(conn->path, "/");
|
||||||
|
|
||||||
if (2 > sscanf(data->change.url,
|
if (2 > sscanf(data->change.url,
|
||||||
"%64[^\n:]://%256[^\n/]%[^\n]",
|
"%64[^\n:]://%512[^\n/]%[^\n]",
|
||||||
conn->protostr, conn->gname, conn->path)) {
|
conn->protostr, conn->gname, conn->path)) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The URL was badly formatted, let's try the browser-style _without_
|
* The URL was badly formatted, let's try the browser-style _without_
|
||||||
* protocol specified like 'http://'.
|
* protocol specified like 'http://'.
|
||||||
*/
|
*/
|
||||||
if((1 > sscanf(data->change.url, "%256[^\n/]%[^\n]",
|
if((1 > sscanf(data->change.url, "%512[^\n/]%[^\n]",
|
||||||
conn->gname, conn->path)) ) {
|
conn->gname, conn->path)) ) {
|
||||||
/*
|
/*
|
||||||
* We couldn't even get this format.
|
* We couldn't even get this format.
|
||||||
@@ -1741,21 +1541,6 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Set timeout if that is being used
|
|
||||||
*************************************************************/
|
|
||||||
if(data->set.timeout || data->set.connecttimeout) {
|
|
||||||
/* We set the timeout on the connection/resolving phase first, separately
|
|
||||||
* from the download/upload part to allow a maximum time on everything */
|
|
||||||
|
|
||||||
/* myalarm() makes a signal get sent when the timeout fires off, and that
|
|
||||||
will abort system calls */
|
|
||||||
if(data->set.connecttimeout)
|
|
||||||
myalarm(data->set.connecttimeout);
|
|
||||||
else
|
|
||||||
myalarm(data->set.timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Setup internals depending on protocol
|
* Setup internals depending on protocol
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
@@ -1996,16 +1781,13 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
* port number of various reasons.
|
* port number of various reasons.
|
||||||
*
|
*
|
||||||
* To be able to detect port number flawlessly, we must not confuse them
|
* To be able to detect port number flawlessly, we must not confuse them
|
||||||
* IPv6-specified addresses in the [0::1] style.
|
* IPv6-specified addresses in the [0::1] style. (RFC2732)
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
|
||||||
if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
|
if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
|
||||||
(']' == endbracket)) {
|
(']' == endbracket)) {
|
||||||
/* this is a IPv6-style specified IP-address */
|
/* This is a (IPv6-style) specified IP-address. We support _any_
|
||||||
#ifndef ENABLE_IPV6
|
IP within brackets to be really generic. */
|
||||||
failf(data, "You haven't enabled IPv6 support");
|
|
||||||
return CURLE_URL_MALFORMAT;
|
|
||||||
#else
|
|
||||||
conn->name++; /* pass the starting bracket */
|
conn->name++; /* pass the starting bracket */
|
||||||
|
|
||||||
tmp = strchr(conn->name, ']');
|
tmp = strchr(conn->name, ']');
|
||||||
@@ -2014,7 +1796,6 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
tmp++; /* pass the ending bracket */
|
tmp++; /* pass the ending bracket */
|
||||||
if(':' != *tmp)
|
if(':' != *tmp)
|
||||||
tmp = NULL; /* no port number available */
|
tmp = NULL; /* no port number available */
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* traditional IPv4-style port-extracting */
|
/* traditional IPv4-style port-extracting */
|
||||||
@@ -2101,7 +1882,6 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
conn = conn_temp; /* use this connection from now on */
|
conn = conn_temp; /* use this connection from now on */
|
||||||
|
|
||||||
/* we need these pointers if we speak over a proxy */
|
/* we need these pointers if we speak over a proxy */
|
||||||
conn->name = conn->gname;
|
|
||||||
conn->hostname = old_conn->gname;
|
conn->hostname = old_conn->gname;
|
||||||
|
|
||||||
free(conn->path); /* free the previously allocated path pointer */
|
free(conn->path); /* free the previously allocated path pointer */
|
||||||
@@ -2153,6 +1933,23 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
ConnectionStore(data, conn);
|
ConnectionStore(data, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Set timeout if that is being used
|
||||||
|
*************************************************************/
|
||||||
|
if(data->set.timeout || data->set.connecttimeout) {
|
||||||
|
/* We set the timeout on the name resolving phase first, separately from
|
||||||
|
* the download/upload part to allow a maximum time on everything. This is
|
||||||
|
* a signal-based timeout, why it won't work and shouldn't be used in
|
||||||
|
* multi-threaded environments. */
|
||||||
|
|
||||||
|
/* myalarm() makes a signal get sent when the timeout fires off, and that
|
||||||
|
will abort system calls */
|
||||||
|
if(data->set.connecttimeout)
|
||||||
|
myalarm(data->set.connecttimeout);
|
||||||
|
else
|
||||||
|
myalarm(data->set.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Resolve the name of the server or proxy
|
* Resolve the name of the server or proxy
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
@@ -2162,38 +1959,34 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
conn->port = conn->remote_port; /* it is the same port */
|
conn->port = conn->remote_port; /* it is the same port */
|
||||||
|
|
||||||
/* Resolve target host right on */
|
/* Resolve target host right on */
|
||||||
if(!conn->hp) {
|
if(!conn->hostaddr) {
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
/* it might already be set if reusing a connection */
|
/* it might already be set if reusing a connection */
|
||||||
conn->hp = Curl_getaddrinfo(data, conn->name, conn->port);
|
conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port,
|
||||||
#else
|
&conn->hostent_buf);
|
||||||
/* it might already be set if reusing a connection */
|
|
||||||
conn->hp = Curl_gethost(data, conn->name, &conn->hostent_buf);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if(!conn->hp)
|
if(!conn->hostaddr) {
|
||||||
{
|
|
||||||
failf(data, "Couldn't resolve host '%s'", conn->name);
|
failf(data, "Couldn't resolve host '%s'", conn->name);
|
||||||
return CURLE_COULDNT_RESOLVE_HOST;
|
return CURLE_COULDNT_RESOLVE_HOST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!conn->hp) {
|
else if(!conn->hostaddr) {
|
||||||
/* This is a proxy that hasn't been resolved yet. It may be resolved
|
/* This is a proxy that hasn't been resolved yet. It may be resolved
|
||||||
if we're reusing an existing connection. */
|
if we're reusing an existing connection. */
|
||||||
|
|
||||||
/* resolve proxy */
|
/* resolve proxy */
|
||||||
#ifdef ENABLE_IPV6
|
/* it might already be set if reusing a connection */
|
||||||
/* it might already be set if reusing a connection */
|
conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port,
|
||||||
conn->hp = Curl_getaddrinfo(data, conn->proxyhost, conn->port);
|
&conn->hostent_buf);
|
||||||
#else
|
|
||||||
conn->hp = Curl_gethost(data, conn->proxyhost, &conn->hostent_buf);
|
if(!conn->hostaddr) {
|
||||||
#endif
|
|
||||||
if(!conn->hp) {
|
|
||||||
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
|
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
|
||||||
return CURLE_COULDNT_RESOLVE_PROXY;
|
return CURLE_COULDNT_RESOLVE_PROXY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
|
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
|
||||||
|
if(data->set.timeout || data->set.connecttimeout)
|
||||||
|
/* switch off signal-based timeouts */
|
||||||
|
myalarm(0);
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Proxy authentication
|
* Proxy authentication
|
||||||
@@ -2227,7 +2020,7 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
|
|
||||||
if(-1 == conn->firstsocket) {
|
if(-1 == conn->firstsocket) {
|
||||||
/* Connect only if not already connected! */
|
/* Connect only if not already connected! */
|
||||||
result = ConnectPlease(data, conn);
|
result = ConnectPlease(conn);
|
||||||
if(CURLE_OK != result)
|
if(CURLE_OK != result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -2250,6 +2043,7 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
|
|
||||||
conn->now = Curl_tvnow(); /* time this *after* the connect is done */
|
conn->now = Curl_tvnow(); /* time this *after* the connect is done */
|
||||||
conn->bytecount = 0;
|
conn->bytecount = 0;
|
||||||
|
conn->headerbytecount = 0;
|
||||||
|
|
||||||
/* Figure out the ip-number and display the first host name it shows: */
|
/* Figure out the ip-number and display the first host name it shows: */
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
@@ -2260,23 +2054,25 @@ static CURLcode Connect(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
const int niflags = NI_NUMERICHOST;
|
const int niflags = NI_NUMERICHOST;
|
||||||
#endif
|
#endif
|
||||||
struct addrinfo *ai = conn->ai;
|
struct addrinfo *ai = conn->serv_addr;
|
||||||
|
|
||||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
|
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
|
||||||
niflags)) {
|
niflags)) {
|
||||||
snprintf(hbuf, sizeof(hbuf), "?");
|
snprintf(hbuf, sizeof(hbuf), "?");
|
||||||
}
|
}
|
||||||
if (ai->ai_canonname) {
|
if (ai->ai_canonname) {
|
||||||
infof(data, "Connected to %s (%s)\n", ai->ai_canonname, hbuf);
|
infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
|
||||||
|
conn->port);
|
||||||
} else {
|
} else {
|
||||||
infof(data, "Connected to %s\n", hbuf);
|
infof(data, "Connected to %s port %d\n", hbuf, conn->port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
(void) memcpy(&in.s_addr, *conn->hp->h_addr_list, sizeof (in.s_addr));
|
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
||||||
infof(data, "Connected to %s (%s)\n", conn->hp->h_name, inet_ntoa(in));
|
infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
|
||||||
|
inet_ntoa(in));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2303,7 +2099,7 @@ CURLcode Curl_connect(struct SessionHandle *data,
|
|||||||
struct connectdata *conn;
|
struct connectdata *conn;
|
||||||
|
|
||||||
/* call the stuff that needs to be called */
|
/* call the stuff that needs to be called */
|
||||||
code = Connect(data, in_connect, allow_port);
|
code = CreateConnection(data, in_connect, allow_port);
|
||||||
|
|
||||||
if(CURLE_OK != code) {
|
if(CURLE_OK != code) {
|
||||||
/* We're not allowed to return failure with memory left allocated
|
/* We're not allowed to return failure with memory left allocated
|
||||||
@@ -2354,7 +2150,7 @@ CURLcode Curl_done(struct connectdata *conn)
|
|||||||
((CURLE_OK == result) && conn->bits.close))
|
((CURLE_OK == result) && conn->bits.close))
|
||||||
result = Curl_disconnect(conn); /* close the connection */
|
result = Curl_disconnect(conn); /* close the connection */
|
||||||
else
|
else
|
||||||
infof(data, "Connection (#%d) left alive\n", conn->connectindex);
|
infof(data, "Connection #%d left intact\n", conn->connectindex);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -2374,6 +2170,6 @@ CURLcode Curl_do(struct connectdata *conn)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
/* This file is for lib internal stuff */
|
/* This file is for lib internal stuff */
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
#include "hostip.h"
|
||||||
|
|
||||||
#define PORT_FTP 21
|
#define PORT_FTP 21
|
||||||
#define PORT_TELNET 23
|
#define PORT_TELNET 23
|
||||||
@@ -223,16 +224,16 @@ struct connectdata {
|
|||||||
#define PROT_FILE (1<<8)
|
#define PROT_FILE (1<<8)
|
||||||
#define PROT_FTPS (1<<9)
|
#define PROT_FTPS (1<<9)
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
Curl_addrinfo *hostaddr; /* IP-protocol independent host info pointer list */
|
||||||
struct addrinfo *hp; /* host info pointer list */
|
|
||||||
struct addrinfo *ai; /* the particular host we use */
|
|
||||||
#else
|
|
||||||
char *hostent_buf; /* pointer to allocated memory for name info */
|
char *hostent_buf; /* pointer to allocated memory for name info */
|
||||||
struct hostent *hp;
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
struct addrinfo *serv_addr; /* the particular host we use */
|
||||||
|
#else
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_in serv_addr;
|
||||||
#endif
|
#endif
|
||||||
char protostr[64]; /* store the protocol string in this buffer */
|
char protostr[64]; /* store the protocol string in this buffer */
|
||||||
char gname[257]; /* store the hostname in this buffer */
|
char gname[513]; /* store the hostname in this buffer */
|
||||||
char *name; /* host name pointer to fool around with */
|
char *name; /* host name pointer to fool around with */
|
||||||
char *path; /* allocated buffer to store the URL's path part in */
|
char *path; /* allocated buffer to store the URL's path part in */
|
||||||
char *hostname; /* hostname to connect, as parsed from url */
|
char *hostname; /* hostname to connect, as parsed from url */
|
||||||
@@ -241,6 +242,7 @@ struct connectdata {
|
|||||||
not the proxy port! */
|
not the proxy port! */
|
||||||
char *ppath;
|
char *ppath;
|
||||||
long bytecount;
|
long bytecount;
|
||||||
|
long headerbytecount; /* only count received headers */
|
||||||
|
|
||||||
char *range; /* range, if used. See README for detailed specification on
|
char *range; /* range, if used. See README for detailed specification on
|
||||||
this syntax. */
|
this syntax. */
|
||||||
@@ -351,8 +353,8 @@ struct connectdata {
|
|||||||
struct PureInfo {
|
struct PureInfo {
|
||||||
int httpcode;
|
int httpcode;
|
||||||
int httpversion;
|
int httpversion;
|
||||||
time_t filetime; /* If requested, this is might get set. It may be 0 if
|
long filetime; /* If requested, this is might get set. Set to -1 if
|
||||||
the time was unretrievable */
|
the time was unretrievable */
|
||||||
long header_size; /* size of read header(s) in bytes */
|
long header_size; /* size of read header(s) in bytes */
|
||||||
long request_size; /* the amount of bytes sent in the request(s) */
|
long request_size; /* the amount of bytes sent in the request(s) */
|
||||||
};
|
};
|
||||||
@@ -371,7 +373,9 @@ struct Progress {
|
|||||||
bool callback; /* set when progress callback is used */
|
bool callback; /* set when progress callback is used */
|
||||||
int width; /* screen width at download start */
|
int width; /* screen width at download start */
|
||||||
int flags; /* see progress.h */
|
int flags; /* see progress.h */
|
||||||
double timespent;
|
|
||||||
|
long timespent;
|
||||||
|
|
||||||
double dlspeed;
|
double dlspeed;
|
||||||
double ulspeed;
|
double ulspeed;
|
||||||
|
|
||||||
@@ -381,9 +385,10 @@ struct Progress {
|
|||||||
|
|
||||||
struct timeval start;
|
struct timeval start;
|
||||||
struct timeval t_startsingle;
|
struct timeval t_startsingle;
|
||||||
#define CURR_TIME 5
|
#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
|
||||||
|
|
||||||
double speeder[ CURR_TIME ];
|
double speeder[ CURR_TIME ];
|
||||||
|
struct timeval speeder_time[ CURR_TIME ];
|
||||||
int speeder_c;
|
int speeder_c;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -441,6 +446,9 @@ struct UrlState {
|
|||||||
long sessionage; /* number of the most recent session */
|
long sessionage; /* number of the most recent session */
|
||||||
|
|
||||||
char scratch[BUFSIZE*2]; /* huge buffer when doing upload CRLF replacing */
|
char scratch[BUFSIZE*2]; /* huge buffer when doing upload CRLF replacing */
|
||||||
|
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
|
||||||
|
This must be set to FALSE every time _easy_perform() is
|
||||||
|
called. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -519,11 +527,13 @@ struct UserDefined {
|
|||||||
struct curl_slist *quote; /* before the transfer */
|
struct curl_slist *quote; /* before the transfer */
|
||||||
struct curl_slist *postquote; /* after the transfer */
|
struct curl_slist *postquote; /* after the transfer */
|
||||||
struct curl_slist *telnet_options; /* linked list of telnet options */
|
struct curl_slist *telnet_options; /* linked list of telnet options */
|
||||||
TimeCond timecondition; /* kind of time/date comparison */
|
curl_TimeCond timecondition; /* kind of time/date comparison */
|
||||||
time_t timevalue; /* what time to compare with */
|
time_t timevalue; /* what time to compare with */
|
||||||
curl_closepolicy closepolicy; /* connection cache close concept */
|
curl_closepolicy closepolicy; /* connection cache close concept */
|
||||||
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
|
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
|
||||||
char *customrequest; /* HTTP/FTP request to use */
|
char *customrequest; /* HTTP/FTP request to use */
|
||||||
|
long httpversion; /* when non-zero, a specific HTTP version requested to
|
||||||
|
be used in the library's request(s) */
|
||||||
char *auth_host; /* if set, this is the allocated string to the host name
|
char *auth_host; /* if set, this is the allocated string to the host name
|
||||||
* to which to send the authorization data to, and no other
|
* to which to send the authorization data to, and no other
|
||||||
* host (which location-following otherwise could lead to)
|
* host (which location-following otherwise could lead to)
|
||||||
|
@@ -108,6 +108,6 @@ char *curl_version(void)
|
|||||||
* local variables:
|
* local variables:
|
||||||
* eval: (load-file "../curl-mode.el")
|
* eval: (load-file "../curl-mode.el")
|
||||||
* end:
|
* end:
|
||||||
* vim600: et sw=2 ts=2 sts=2 tw=78 fdm=marker
|
* vim600: fdm=marker
|
||||||
* vim<600: et sw=2 ts=2 sts=2 tw=78
|
* vim: et sw=2 ts=2 sts=2 tw=78
|
||||||
*/
|
*/
|
||||||
|
28
ltmain.sh
28
ltmain.sh
@@ -56,7 +56,7 @@ modename="$progname"
|
|||||||
PROGRAM=ltmain.sh
|
PROGRAM=ltmain.sh
|
||||||
PACKAGE=libtool
|
PACKAGE=libtool
|
||||||
VERSION=1.4.2
|
VERSION=1.4.2
|
||||||
TIMESTAMP=" (1.922.2.53 2001/09/11 03:18:52)"
|
TIMESTAMP=" (1.922.2.54 2001/09/11 03:33:37)"
|
||||||
|
|
||||||
default_mode=
|
default_mode=
|
||||||
help="Try \`$progname --help' for more information."
|
help="Try \`$progname --help' for more information."
|
||||||
@@ -4273,19 +4273,31 @@ relink_command=\"$relink_command\""
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Do a test to see if this is really a libtool program.
|
# Do a test to see if this is really a libtool program.
|
||||||
if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
|
#if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
|
||||||
|
case $host in
|
||||||
|
*cygwin*|*mingw*)
|
||||||
|
wrapper=`echo $file | sed -e 's,.exe$,,'`
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
wrapper=$file
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if (sed -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
|
||||||
|
|
||||||
notinst_deplibs=
|
notinst_deplibs=
|
||||||
relink_command=
|
relink_command=
|
||||||
|
|
||||||
# If there is no directory component, then add one.
|
# If there is no directory component, then add one.
|
||||||
case $file in
|
case $file in
|
||||||
*/* | *\\*) . $file ;;
|
#*/* | *\\*) . $file ;;
|
||||||
*) . ./$file ;;
|
#*) . ./$file ;;
|
||||||
|
*/* | *\\*) . $wrapper ;;
|
||||||
|
*) . ./$wrapper ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Check the variables that should have been set.
|
# Check the variables that should have been set.
|
||||||
if test -z "$notinst_deplibs"; then
|
if test -z "$notinst_deplibs"; then
|
||||||
$echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
|
$echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -4310,8 +4322,10 @@ relink_command=\"$relink_command\""
|
|||||||
relink_command=
|
relink_command=
|
||||||
# If there is no directory component, then add one.
|
# If there is no directory component, then add one.
|
||||||
case $file in
|
case $file in
|
||||||
*/* | *\\*) . $file ;;
|
#*/* | *\\*) . $file ;;
|
||||||
*) . ./$file ;;
|
#*) . ./$file ;;
|
||||||
|
*/* | *\\*) . $wrapper ;;
|
||||||
|
*) . ./$wrapper ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
outputname=
|
outputname=
|
||||||
|
44
maketgz
44
maketgz
@@ -61,7 +61,8 @@ findprog()
|
|||||||
# Enforce a rerun of configure (updates the VERSION)
|
# Enforce a rerun of configure (updates the VERSION)
|
||||||
#
|
#
|
||||||
|
|
||||||
./config.status --recheck
|
echo "Re-running config.status"
|
||||||
|
./config.status --recheck >/dev/null
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
@@ -73,7 +74,7 @@ if { findprog automake >/dev/null 2>/dev/null; } then
|
|||||||
echo "- Could not find or run automake, I hope you know what you're doing!"
|
echo "- Could not find or run automake, I hope you know what you're doing!"
|
||||||
else
|
else
|
||||||
echo "Runs automake --include-deps"
|
echo "Runs automake --include-deps"
|
||||||
automake --include-deps Makefile
|
automake --include-deps Makefile >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
@@ -84,7 +85,44 @@ make html
|
|||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
# Now run make dist
|
# Now run make dist to generate a tar.gz archive
|
||||||
#
|
#
|
||||||
|
|
||||||
|
targz="curl-$version.tar.gz"
|
||||||
make dist
|
make dist
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# Now make a bz2 archive from the tar.gz original
|
||||||
|
#
|
||||||
|
|
||||||
|
bzip2="curl-$version.tar.bz2"
|
||||||
|
echo "Generating $bzip2"
|
||||||
|
gzip -dc $targz | bzip2 - > $bzip2
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# Now make a zip archive from the tar.gz original
|
||||||
|
#
|
||||||
|
makezip ()
|
||||||
|
{
|
||||||
|
rm -rf $tempdir
|
||||||
|
mkdir $tempdir
|
||||||
|
cd $tempdir
|
||||||
|
gzip -dc ../$targz | tar -xf -
|
||||||
|
find . | zip $zip -@ >/dev/null
|
||||||
|
mv $zip ../
|
||||||
|
cd ..
|
||||||
|
rm -rf $tempdir
|
||||||
|
}
|
||||||
|
|
||||||
|
zip="curl-$version.zip"
|
||||||
|
echo "Generating $zip"
|
||||||
|
tempdir=".builddir"
|
||||||
|
makezip
|
||||||
|
|
||||||
|
echo "------------------"
|
||||||
|
echo "maketgz report:"
|
||||||
|
echo ""
|
||||||
|
ls -l $targz $bzip2 $zip
|
||||||
|
|
||||||
|
@@ -167,6 +167,37 @@ while(<STDIN>) {
|
|||||||
$fopens--;
|
$fopens--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
# ADDR url.c:1282 getaddrinfo() = 0x5ddd
|
||||||
|
elsif($_ =~ /^ADDR ([^:]*):(\d*) (.*)/) {
|
||||||
|
# generic match for the filename+linenumber
|
||||||
|
$source = $1;
|
||||||
|
$linenum = $2;
|
||||||
|
$function = $3;
|
||||||
|
|
||||||
|
if($function =~ /getaddrinfo\(\) = (\(nil\)|0x([0-9a-f]*))/) {
|
||||||
|
my $add = $2;
|
||||||
|
if($add eq "(nil)") {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$addrinfo{$add}=1;
|
||||||
|
$addrinfofile{$add}="$source:$linenum";
|
||||||
|
$addrinfos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# fclose(0x1026c8)
|
||||||
|
elsif($function =~ /freeaddrinfo\(0x([0-9a-f]*)\)/) {
|
||||||
|
if(!$addrinfo{$1}) {
|
||||||
|
print "freeaddrinfo() without getaddrinfo(): $line\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$addrinfo{$1}=0;
|
||||||
|
$addrinfos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print "Not recognized prefix line: $line\n";
|
print "Not recognized prefix line: $line\n";
|
||||||
@@ -203,6 +234,15 @@ if($fopens) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($addrinfos) {
|
||||||
|
print "IPv6-style name resolve data left at:\n";
|
||||||
|
for(keys %addrinfofile) {
|
||||||
|
if($addrinfo{$_} == 1) {
|
||||||
|
print "getaddrinfo() called at ".$addrinfofile{$_}."\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($verbose) {
|
if($verbose) {
|
||||||
print "Mallocs: $mallocs\n",
|
print "Mallocs: $mallocs\n",
|
||||||
"Reallocs: $reallocs\n",
|
"Reallocs: $reallocs\n",
|
||||||
|
@@ -1 +1,3 @@
|
|||||||
|
SUBDIRS = cygwin
|
||||||
|
|
||||||
EXTRA_DIST = README
|
EXTRA_DIST = README
|
||||||
|
34
packages/Win32/cygwin/Makefile.am
Normal file
34
packages/Win32/cygwin/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
EXTRA_DIST = README
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build a Cygwin binary tar ball
|
||||||
|
#
|
||||||
|
# Read the README file for details on using this Makefile
|
||||||
|
#
|
||||||
|
# NOTE: As I'm not particularly familiar with Makefiles, this was the
|
||||||
|
# best I could come up with. It should probably be enhanced someday
|
||||||
|
# to actually use the correct target and pre-requisite names, etc...
|
||||||
|
# If anyone else wants to volunteer, feel free ;-)
|
||||||
|
#
|
||||||
|
|
||||||
|
# Cygwin build number (default to "1")
|
||||||
|
CYGBUILD = 1
|
||||||
|
|
||||||
|
# Cygwin tarball build dir (fully-qualified name, gets deleted when done)
|
||||||
|
cygwintmp = $(CURDIR)/cygwinbin-builddir
|
||||||
|
|
||||||
|
cygwinbin:
|
||||||
|
rm -rf $(cygwintmp)
|
||||||
|
$(MAKE) -C $(top_builddir) install prefix=$(cygwintmp)/usr
|
||||||
|
$(mkinstalldirs) $(cygwintmp)/usr/doc/Cygwin \
|
||||||
|
$(cygwintmp)/usr/doc/$(PACKAGE)-$(VERSION)
|
||||||
|
cd $(top_srcdir); \
|
||||||
|
cp packages/Win32/cygwin/README \
|
||||||
|
$(cygwintmp)/usr/doc/Cygwin/$(PACKAGE)-$(VERSION)-$(CYGBUILD).README
|
||||||
|
cd $(top_srcdir) ; \
|
||||||
|
cp CHANGES LEGAL MPL-1.1.txt README docs/FAQ docs/FEATURES docs/TODO \
|
||||||
|
$(cygwintmp)/usr/doc/$(PACKAGE)-$(VERSION)
|
||||||
|
cd $(cygwintmp) ; \
|
||||||
|
tar cjf $(PACKAGE)-$(VERSION)-$(CYGBUILD).tar.bz2 usr
|
||||||
|
mv $(cygwintmp)/$(PACKAGE)-$(VERSION)-$(CYGBUILD).tar.bz2 . \
|
||||||
|
&& rm -rf $(cygwintmp)
|
60
packages/Win32/cygwin/README
Normal file
60
packages/Win32/cygwin/README
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
Curl is a tool for transferring files with URL syntax, supporting FTP, FTPS,
|
||||||
|
HTTP, HTTPS, GOPHER, TELNET, DICT, FILE and LDAP. Curl supports HTTPS
|
||||||
|
certificates, HTTP POST, HTTP PUT, FTP uploading, kerberos, HTTP form based
|
||||||
|
upload, proxies, cookies, user+password authentication, file transfer resume,
|
||||||
|
http proxy tunneling and a busload of other useful tricks.
|
||||||
|
See /usr/doc/curl-<version>/FEATURES for more info.
|
||||||
|
|
||||||
|
cURL (as of 7.9.1) builds 100% cleanly OOTB.
|
||||||
|
|
||||||
|
The Cygwin specific source files (README and a Makefile for
|
||||||
|
building binary tarballs) are not in a CYGWIN-PATCHES directory.
|
||||||
|
They are at: <srctop>/packages/Win32/cygwin/
|
||||||
|
|
||||||
|
|
||||||
|
Direct Dependencies:
|
||||||
|
OpenSSL 0.9.6b
|
||||||
|
(*) cURL can be built without SSL support: ./configure --without-ssl
|
||||||
|
|
||||||
|
|
||||||
|
Canonical Homepage:
|
||||||
|
http://curl.haxx.se/
|
||||||
|
|
||||||
|
|
||||||
|
Canonical Download:
|
||||||
|
http://curl.haxx.se/download.html
|
||||||
|
|
||||||
|
|
||||||
|
Build Instructions:
|
||||||
|
Download the source, move it to a location of your choosing, and then:
|
||||||
|
|
||||||
|
$ tar xjf curl-<ver>-X-src.tar.bz2
|
||||||
|
$ cd curl-<ver>-X
|
||||||
|
$ ./configure --prefix=/usr
|
||||||
|
$ make
|
||||||
|
$ make test # optional, requires perl
|
||||||
|
$ make install # (*)
|
||||||
|
|
||||||
|
(*) LibTool 1.4.2 had a bug related to cygwin's use of ".exe" extensions,
|
||||||
|
such that "make install" blew up at curl.exe. See this URL for details:
|
||||||
|
http://mail.gnu.org/pipermail/libtool/2001-September/005549.html
|
||||||
|
The copy of ltmain.sh that is distributed with cURL includes this patch.
|
||||||
|
|
||||||
|
|
||||||
|
Packaging Instructions:
|
||||||
|
To create a new binary tarball for cygwin's setup.exe, the first step is to
|
||||||
|
do a clean build (./configure and make). The 'make install' step is optional.
|
||||||
|
Then do:
|
||||||
|
|
||||||
|
$ cd curl-<ver>-X
|
||||||
|
$ make cygwinbin CYGBUILD=X
|
||||||
|
|
||||||
|
where "X" is the cygwin release number (e.g. the "-1" in curl-7.9.3-1).
|
||||||
|
If you leave off "CYGBUILD=X", X defaults to 1.
|
||||||
|
|
||||||
|
Assuming everything worked properly, you'll find your cygwin
|
||||||
|
binary tarball in the curl-<ver>-X/packages/Win32/cygwin/ directory.
|
||||||
|
|
||||||
|
|
||||||
|
Cygwin port maintained by:
|
||||||
|
Kevin Roth <kproth at bigfoot dot com>
|
@@ -1,92 +0,0 @@
|
|||||||
Revision history for Perl extension Curl::easy.
|
|
||||||
Check out the file README for more info.
|
|
||||||
|
|
||||||
1.1.8 Thu Sep 20 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Re-generate CURLOPT_ constants from curl.h and enhance makefile
|
|
||||||
to allow this to be repeated in future or for older versions of
|
|
||||||
libcurl. Constants up-to-date for libcurl-7.9(pre)
|
|
||||||
- Split tests into t/*.t to simplify each case
|
|
||||||
- Add test cases for new SSL switches. This needs ca-bundle.crt
|
|
||||||
(from mod_ssl) for verifying test cases.
|
|
||||||
|
|
||||||
1.1.7 Thu Sep 13 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Documentation Update only - Explicitly state that Curl_easy
|
|
||||||
is released under the MIT-X/MPL dual licence. No code changes.
|
|
||||||
|
|
||||||
1.1.6 Mon Sep 10 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Fix segfault due to changes in header callback behaviour
|
|
||||||
since curl-7.8.1-pre3
|
|
||||||
|
|
||||||
1.1.5 Fri Apr 20 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Add latest CURLOPT_ and CURLINFO_ constants to the constants list
|
|
||||||
|
|
||||||
1.1.4 Fri Apr 20 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Fix case where curl_slists such as 'HTTPHEADERS' need to
|
|
||||||
be re-set over persistant requests
|
|
||||||
|
|
||||||
1.1.3 Wed Apr 18 2001: - Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
- Change/shorten module function names: Curl::easy::curl_easy_setopt
|
|
||||||
becomes Curl::easy::setopt etc. This requires minor changes to existing
|
|
||||||
scripts....
|
|
||||||
- Added callback function support to pass arbitrary SV * (including
|
|
||||||
FILE globs) from perl through libcurl to the perl callback.
|
|
||||||
- Make callbacks still work with existing scripts which use STDIO
|
|
||||||
- Initial support for libcurl 7.7.2 HEADERFUNCTION callback feature
|
|
||||||
- Minor API cleanups/changes in the callback function signatures
|
|
||||||
- Added Curl::easy::version function to return curl version string
|
|
||||||
- Callback documentation added in easy.pm
|
|
||||||
- More tests in test.pl
|
|
||||||
|
|
||||||
1.1.2 Mon Apr 16 2001: - Georg Horn <horn@koblenz-net.de>
|
|
||||||
- Added support for callback functions. This is for the curl_easy_setopt()
|
|
||||||
options WRITEFUNCTION, READFUNCTION, PROGRESSFUNCTION and PASSWDFUNCTION.
|
|
||||||
Still missing, but not really neccessary: Passing a FILE * pointer,
|
|
||||||
that is passed in from libcurl, on to the perl callback function.
|
|
||||||
- Various cleanups, fixes and enhancements to easy.xs and test.pl.
|
|
||||||
|
|
||||||
1.1.1 Thu Apr 12 2001:
|
|
||||||
- Made more options of curl_easy_setopt() work: Options that require
|
|
||||||
a list of curl_slist structs to be passed in, like CURLOPT_HTTPHEADER,
|
|
||||||
are now working by passing a perl array containing the list elements.
|
|
||||||
As always, look at the test script test.pl for an example.
|
|
||||||
|
|
||||||
1.1.0 Wed Apr 11 2001:
|
|
||||||
- tested against libcurl 7.7
|
|
||||||
- Added new function Curl::easy::internal_setopt(). By calling
|
|
||||||
Curl::easy::internal_setopt(Curl::easy::USE_INTERNAL_VARS, 1);
|
|
||||||
the headers and content of the fetched page are no longer stored
|
|
||||||
into files (or written to stdout) but are stored into internal
|
|
||||||
Variables $Curl::easy::headers and $Curl::easy::content.
|
|
||||||
|
|
||||||
1.0.2 Tue Oct 10 2000:
|
|
||||||
- runs with libcurl 7.4
|
|
||||||
- modified curl_easy_getinfo(). It now calls curl_getinfo() that has
|
|
||||||
been added to libcurl in version 7.4.
|
|
||||||
|
|
||||||
1.0.1 Tue Oct 10 2000:
|
|
||||||
- Added some missing features of curl_easy_setopt():
|
|
||||||
- CURLOPT_ERRORBUFFER now works by passing the name of a perl
|
|
||||||
variable that shall be crated and the errormessage (if any)
|
|
||||||
be stored to.
|
|
||||||
- Passing filehandles (Options FILE, INFILE and WRITEHEADER) now works.
|
|
||||||
Have a look at test.pl to see how it works...
|
|
||||||
|
|
||||||
- Added a new function, curl_easy_getinfo(), that for now always
|
|
||||||
returns the number of bytes that where written to disk during the last
|
|
||||||
download. If the curl_easy_getinfo() function is included in libcurl,
|
|
||||||
(as promised by Daniel ;-)) i will turn this into just a call to this
|
|
||||||
function.
|
|
||||||
|
|
||||||
1.0 Thu Oct 5 2000:
|
|
||||||
- first released version
|
|
||||||
- runs with libcurl 7.3
|
|
||||||
- some features of curl_easy_setopt() are still missing:
|
|
||||||
- passing function pointers doesn't work (options WRITEFUNCTION,
|
|
||||||
READFUNCTION and PROGRESSFUNCTION).
|
|
||||||
- passing FILE * pointers doesn't work (options FILE, INFILE and
|
|
||||||
WRITEHEADER).
|
|
||||||
- passing linked lists doesn't work (options HTTPHEADER and
|
|
||||||
HTTPPOST).
|
|
||||||
- setting the buffer where to store error messages in doesn't work
|
|
||||||
(option ERRORBUFFER).
|
|
||||||
|
|
@@ -1,16 +0,0 @@
|
|||||||
Changes
|
|
||||||
MANIFEST
|
|
||||||
Makefile.PL
|
|
||||||
README
|
|
||||||
easy.pm
|
|
||||||
easy.xs
|
|
||||||
curlopt-constants.c
|
|
||||||
t/00constants.t
|
|
||||||
t/01basic.t
|
|
||||||
t/02header-callback.t
|
|
||||||
t/03body-callback.t
|
|
||||||
t/04abort-test.t
|
|
||||||
t/05progress.t
|
|
||||||
t/06http-post.t
|
|
||||||
t/07ftp-upload.t
|
|
||||||
t/08ssl.t
|
|
@@ -1,87 +0,0 @@
|
|||||||
# Makefile.PL for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
use ExtUtils::MakeMaker;
|
|
||||||
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
|
|
||||||
# the contents of the Makefile that is written.
|
|
||||||
WriteMakefile(
|
|
||||||
'NAME' => 'Curl::easy',
|
|
||||||
'VERSION_FROM' => 'easy.pm', # finds $VERSION
|
|
||||||
'LIBS' => ['-lcurl '], # e.g., '-lm'
|
|
||||||
'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
|
|
||||||
'INC' => '', # e.g., '-I/usr/include/other'
|
|
||||||
'clean' => {FILES => "head.out body.out"}
|
|
||||||
);
|
|
||||||
|
|
||||||
#
|
|
||||||
# This utility helper generates the constants function from curl.h
|
|
||||||
#
|
|
||||||
# It is normally only used by the maintainer, but if you're curl is older
|
|
||||||
# or missing some constants, you can delete curlopt-constants.c and re-run 'perl Makefile.PL'
|
|
||||||
#
|
|
||||||
|
|
||||||
if (!open(CONSTANTS,"<curlopt-constants.c")) {
|
|
||||||
print "Rebuilding curlopt-constants.c for your libcurl version\n";
|
|
||||||
close(CONSTANTS);
|
|
||||||
|
|
||||||
#
|
|
||||||
# You may need to specify where to find curl.h on your platform
|
|
||||||
# These are guesses only
|
|
||||||
#
|
|
||||||
my $curl_h;
|
|
||||||
HEADER: foreach my $try (qw(
|
|
||||||
|
|
||||||
curl.h
|
|
||||||
../../include/curl.h
|
|
||||||
/usr/include/curl/curl.h
|
|
||||||
/usr/local/include/curl/curl.h
|
|
||||||
C:\\INCLUDE\\CURL\\CURL.H
|
|
||||||
|
|
||||||
))
|
|
||||||
{
|
|
||||||
if (-e $try) {
|
|
||||||
$curl_h=$try;
|
|
||||||
last HEADER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined($curl_h)) {
|
|
||||||
die "Could not rebuild curlopt-constants.c - can't find curl.h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "Found curl.h in $curl_h\n";
|
|
||||||
open (CURL_H,"<".$curl_h) or die "Can't open curl.h\n";
|
|
||||||
my %types;
|
|
||||||
my %codes;
|
|
||||||
while(<CURL_H>) {
|
|
||||||
if ($_ =~ m/CINIT\(/ and $_ !~ m/#/) {
|
|
||||||
my ($option,$type,$code)=m/.*CINIT\((\w*)\s*,\s*(\w+)\s*,\s*(\d+).*/;
|
|
||||||
$types{$option}=$type;
|
|
||||||
$codes{$option}=$code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(CURL_H);
|
|
||||||
|
|
||||||
# some things are ifdefed out...
|
|
||||||
foreach my $ifdef0 (qw(FLAGS PROGRESSMODE))
|
|
||||||
{
|
|
||||||
delete $types{$ifdef0}; delete $codes{$ifdef0};
|
|
||||||
}
|
|
||||||
|
|
||||||
open(CURL_XS,">curlopt-constants.c") or die "Can't write curlopt-constants.c\n";
|
|
||||||
foreach my $next_initial ('A'..'Z') {
|
|
||||||
print CURL_XS " case '$next_initial':\n";
|
|
||||||
my $count=0;
|
|
||||||
foreach my $option (sort keys %types) {
|
|
||||||
my $initial=substr($option,0,1);
|
|
||||||
if ($next_initial eq $initial) {
|
|
||||||
print CURL_XS " if (strEQ(name, \"$option\")) return CURLOPT_$option;\n";
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($count) {
|
|
||||||
print CURL_XS " break;\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(CURL_XS);
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
SUBDIRS = t
|
|
||||||
|
|
||||||
EXTRA_DIST = Changes easy.pm easy.xs curlopt-constants.c Makefile.PL MANIFEST README
|
|
@@ -1,40 +0,0 @@
|
|||||||
README for Perl extension Curl::easy.
|
|
||||||
|
|
||||||
The perl module Curl::easy provides an interface to the cURL library "libcurl".
|
|
||||||
See http://curl.haxx.se/ for more information on cURL and libcurl.
|
|
||||||
|
|
||||||
This module requires libcurl and the corresponding headerfiles to be
|
|
||||||
installed. You then may install this module via the usual way:
|
|
||||||
|
|
||||||
perl Makefile.PL
|
|
||||||
make
|
|
||||||
make test
|
|
||||||
make install
|
|
||||||
|
|
||||||
If you have an older version of libcurl, you can remove 'curlopt-constants.c'
|
|
||||||
and have it rebuilt by 'perl Makefile.PL'.
|
|
||||||
|
|
||||||
You can also do this for a later version of libcurl, except currently
|
|
||||||
you will have to update the module EXPORTS list manually.
|
|
||||||
|
|
||||||
The module provides the same functionality as libcurl provides to C programs,
|
|
||||||
please refer to the documentation of libcurl. Some examples may be found in
|
|
||||||
t/*.t.
|
|
||||||
|
|
||||||
This software is distributed AS IS, WITHOUT WARRANTY OF ANY KIND, either
|
|
||||||
express or implied. Send praise, patches, money, beer and pizza to the author.
|
|
||||||
Send complaints to /dev/null. ;-)
|
|
||||||
|
|
||||||
The original author of this software is Georg Horn <horn@koblenz-net.de>
|
|
||||||
Parts of the callback support, tests and documentation have been added by
|
|
||||||
Cris Bailiff <c.bailiff@devsecure.com> and Forrest Cahoon <forrest.cahoon@merrillcorp.com>
|
|
||||||
|
|
||||||
The current maintainer is Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
|
|
||||||
The latest version can be downloaded from http://curl.haxx.se/libcurl/perl/
|
|
||||||
|
|
||||||
Copyright (C) 2000, Daniel Stenberg, , et al.
|
|
||||||
You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
||||||
copies of the Software, and permit persons to whom the Software is
|
|
||||||
furnished to do so, under the terms of the MPL or the MIT/X-derivate
|
|
||||||
licenses. You may pick one of these licenses.
|
|
@@ -1,125 +0,0 @@
|
|||||||
case 'A':
|
|
||||||
if (strEQ(name, "AUTOREFERER")) return CURLOPT_AUTOREFERER;
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
if (strEQ(name, "CAINFO")) return CURLOPT_CAINFO;
|
|
||||||
if (strEQ(name, "CLOSEFUNCTION")) return CURLOPT_CLOSEFUNCTION;
|
|
||||||
if (strEQ(name, "CLOSEPOLICY")) return CURLOPT_CLOSEPOLICY;
|
|
||||||
if (strEQ(name, "CONNECTTIMEOUT")) return CURLOPT_CONNECTTIMEOUT;
|
|
||||||
if (strEQ(name, "COOKIE")) return CURLOPT_COOKIE;
|
|
||||||
if (strEQ(name, "COOKIEFILE")) return CURLOPT_COOKIEFILE;
|
|
||||||
if (strEQ(name, "COOKIEJAR")) return CURLOPT_COOKIEJAR;
|
|
||||||
if (strEQ(name, "CRLF")) return CURLOPT_CRLF;
|
|
||||||
if (strEQ(name, "CUSTOMREQUEST")) return CURLOPT_CUSTOMREQUEST;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
if (strEQ(name, "EGDSOCKET")) return CURLOPT_EGDSOCKET;
|
|
||||||
if (strEQ(name, "ERRORBUFFER")) return CURLOPT_ERRORBUFFER;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
if (strEQ(name, "FAILONERROR")) return CURLOPT_FAILONERROR;
|
|
||||||
if (strEQ(name, "FILE")) return CURLOPT_FILE;
|
|
||||||
if (strEQ(name, "FILETIME")) return CURLOPT_FILETIME;
|
|
||||||
if (strEQ(name, "FOLLOWLOCATION")) return CURLOPT_FOLLOWLOCATION;
|
|
||||||
if (strEQ(name, "FORBID_REUSE")) return CURLOPT_FORBID_REUSE;
|
|
||||||
if (strEQ(name, "FRESH_CONNECT")) return CURLOPT_FRESH_CONNECT;
|
|
||||||
if (strEQ(name, "FTPAPPEND")) return CURLOPT_FTPAPPEND;
|
|
||||||
if (strEQ(name, "FTPASCII")) return CURLOPT_FTPASCII;
|
|
||||||
if (strEQ(name, "FTPLISTONLY")) return CURLOPT_FTPLISTONLY;
|
|
||||||
if (strEQ(name, "FTPPORT")) return CURLOPT_FTPPORT;
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
case 'H':
|
|
||||||
if (strEQ(name, "HEADER")) return CURLOPT_HEADER;
|
|
||||||
if (strEQ(name, "HEADERFUNCTION")) return CURLOPT_HEADERFUNCTION;
|
|
||||||
if (strEQ(name, "HTTPGET")) return CURLOPT_HTTPGET;
|
|
||||||
if (strEQ(name, "HTTPHEADER")) return CURLOPT_HTTPHEADER;
|
|
||||||
if (strEQ(name, "HTTPPOST")) return CURLOPT_HTTPPOST;
|
|
||||||
if (strEQ(name, "HTTPPROXYTUNNEL")) return CURLOPT_HTTPPROXYTUNNEL;
|
|
||||||
if (strEQ(name, "HTTPREQUEST")) return CURLOPT_HTTPREQUEST;
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
if (strEQ(name, "INFILE")) return CURLOPT_INFILE;
|
|
||||||
if (strEQ(name, "INFILESIZE")) return CURLOPT_INFILESIZE;
|
|
||||||
if (strEQ(name, "INTERFACE")) return CURLOPT_INTERFACE;
|
|
||||||
break;
|
|
||||||
case 'J':
|
|
||||||
case 'K':
|
|
||||||
if (strEQ(name, "KRB4LEVEL")) return CURLOPT_KRB4LEVEL;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
if (strEQ(name, "LOW_SPEED_LIMIT")) return CURLOPT_LOW_SPEED_LIMIT;
|
|
||||||
if (strEQ(name, "LOW_SPEED_TIME")) return CURLOPT_LOW_SPEED_TIME;
|
|
||||||
break;
|
|
||||||
case 'M':
|
|
||||||
if (strEQ(name, "MAXCONNECTS")) return CURLOPT_MAXCONNECTS;
|
|
||||||
if (strEQ(name, "MAXREDIRS")) return CURLOPT_MAXREDIRS;
|
|
||||||
if (strEQ(name, "MUTE")) return CURLOPT_MUTE;
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
if (strEQ(name, "NETRC")) return CURLOPT_NETRC;
|
|
||||||
if (strEQ(name, "NOBODY")) return CURLOPT_NOBODY;
|
|
||||||
if (strEQ(name, "NOPROGRESS")) return CURLOPT_NOPROGRESS;
|
|
||||||
if (strEQ(name, "NOTHING")) return CURLOPT_NOTHING;
|
|
||||||
break;
|
|
||||||
case 'O':
|
|
||||||
case 'P':
|
|
||||||
if (strEQ(name, "PASSWDDATA")) return CURLOPT_PASSWDDATA;
|
|
||||||
if (strEQ(name, "PASSWDFUNCTION")) return CURLOPT_PASSWDFUNCTION;
|
|
||||||
if (strEQ(name, "PORT")) return CURLOPT_PORT;
|
|
||||||
if (strEQ(name, "POST")) return CURLOPT_POST;
|
|
||||||
if (strEQ(name, "POSTFIELDS")) return CURLOPT_POSTFIELDS;
|
|
||||||
if (strEQ(name, "POSTFIELDSIZE")) return CURLOPT_POSTFIELDSIZE;
|
|
||||||
if (strEQ(name, "POSTQUOTE")) return CURLOPT_POSTQUOTE;
|
|
||||||
if (strEQ(name, "PROGRESSDATA")) return CURLOPT_PROGRESSDATA;
|
|
||||||
if (strEQ(name, "PROGRESSFUNCTION")) return CURLOPT_PROGRESSFUNCTION;
|
|
||||||
if (strEQ(name, "PROXY")) return CURLOPT_PROXY;
|
|
||||||
if (strEQ(name, "PROXYPORT")) return CURLOPT_PROXYPORT;
|
|
||||||
if (strEQ(name, "PROXYUSERPWD")) return CURLOPT_PROXYUSERPWD;
|
|
||||||
if (strEQ(name, "PUT")) return CURLOPT_PUT;
|
|
||||||
break;
|
|
||||||
case 'Q':
|
|
||||||
if (strEQ(name, "QUOTE")) return CURLOPT_QUOTE;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
if (strEQ(name, "RANDOM_FILE")) return CURLOPT_RANDOM_FILE;
|
|
||||||
if (strEQ(name, "RANGE")) return CURLOPT_RANGE;
|
|
||||||
if (strEQ(name, "READFUNCTION")) return CURLOPT_READFUNCTION;
|
|
||||||
if (strEQ(name, "REFERER")) return CURLOPT_REFERER;
|
|
||||||
if (strEQ(name, "RESUME_FROM")) return CURLOPT_RESUME_FROM;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
if (strEQ(name, "SSLCERT")) return CURLOPT_SSLCERT;
|
|
||||||
if (strEQ(name, "SSLCERTPASSWD")) return CURLOPT_SSLCERTPASSWD;
|
|
||||||
if (strEQ(name, "SSLVERSION")) return CURLOPT_SSLVERSION;
|
|
||||||
if (strEQ(name, "SSL_CIPHER_LIST")) return CURLOPT_SSL_CIPHER_LIST;
|
|
||||||
if (strEQ(name, "SSL_VERIFYHOST")) return CURLOPT_SSL_VERIFYHOST;
|
|
||||||
if (strEQ(name, "SSL_VERIFYPEER")) return CURLOPT_SSL_VERIFYPEER;
|
|
||||||
if (strEQ(name, "STDERR")) return CURLOPT_STDERR;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
if (strEQ(name, "TELNETOPTIONS")) return CURLOPT_TELNETOPTIONS;
|
|
||||||
if (strEQ(name, "TIMECONDITION")) return CURLOPT_TIMECONDITION;
|
|
||||||
if (strEQ(name, "TIMEOUT")) return CURLOPT_TIMEOUT;
|
|
||||||
if (strEQ(name, "TIMEVALUE")) return CURLOPT_TIMEVALUE;
|
|
||||||
if (strEQ(name, "TRANSFERTEXT")) return CURLOPT_TRANSFERTEXT;
|
|
||||||
break;
|
|
||||||
case 'U':
|
|
||||||
if (strEQ(name, "UPLOAD")) return CURLOPT_UPLOAD;
|
|
||||||
if (strEQ(name, "URL")) return CURLOPT_URL;
|
|
||||||
if (strEQ(name, "USERAGENT")) return CURLOPT_USERAGENT;
|
|
||||||
if (strEQ(name, "USERPWD")) return CURLOPT_USERPWD;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
if (strEQ(name, "VERBOSE")) return CURLOPT_VERBOSE;
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
if (strEQ(name, "WRITEFUNCTION")) return CURLOPT_WRITEFUNCTION;
|
|
||||||
if (strEQ(name, "WRITEHEADER")) return CURLOPT_WRITEHEADER;
|
|
||||||
if (strEQ(name, "WRITEINFO")) return CURLOPT_WRITEINFO;
|
|
||||||
break;
|
|
||||||
case 'X':
|
|
||||||
case 'Y':
|
|
||||||
case 'Z':
|
|
@@ -1,288 +0,0 @@
|
|||||||
# Perl interface for libcurl. Check out the file README for more info.
|
|
||||||
|
|
||||||
package Curl::easy;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Carp;
|
|
||||||
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
|
|
||||||
|
|
||||||
require Exporter;
|
|
||||||
require DynaLoader;
|
|
||||||
require AutoLoader;
|
|
||||||
|
|
||||||
@ISA = qw(Exporter DynaLoader);
|
|
||||||
# Items to export into callers namespace by default. Note: do not export
|
|
||||||
# names by default without a very good reason. Use EXPORT_OK instead.
|
|
||||||
# Do not simply export all your public functions/methods/constants.
|
|
||||||
@EXPORT = qw(
|
|
||||||
CURLOPT_AUTOREFERER
|
|
||||||
CURLOPT_CAINFO
|
|
||||||
CURLOPT_CLOSEFUNCTION
|
|
||||||
CURLOPT_CLOSEPOLICY
|
|
||||||
CURLOPT_CONNECTTIMEOUT
|
|
||||||
CURLOPT_COOKIE
|
|
||||||
CURLOPT_COOKIEFILE
|
|
||||||
CURLOPT_COOKIEJAR
|
|
||||||
CURLOPT_CRLF
|
|
||||||
CURLOPT_CUSTOMREQUEST
|
|
||||||
CURLOPT_EGDSOCKET
|
|
||||||
CURLOPT_ERRORBUFFER
|
|
||||||
CURLOPT_FAILONERROR
|
|
||||||
CURLOPT_FILE
|
|
||||||
CURLOPT_FILETIME
|
|
||||||
CURLOPT_FOLLOWLOCATION
|
|
||||||
CURLOPT_FORBID_REUSE
|
|
||||||
CURLOPT_FRESH_CONNECT
|
|
||||||
CURLOPT_FTPAPPEND
|
|
||||||
CURLOPT_FTPASCII
|
|
||||||
CURLOPT_FTPLISTONLY
|
|
||||||
CURLOPT_FTPPORT
|
|
||||||
CURLOPT_HEADER
|
|
||||||
CURLOPT_HEADERFUNCTION
|
|
||||||
CURLOPT_HTTPGET
|
|
||||||
CURLOPT_HTTPHEADER
|
|
||||||
CURLOPT_HTTPPOST
|
|
||||||
CURLOPT_HTTPPROXYTUNNEL
|
|
||||||
CURLOPT_HTTPREQUEST
|
|
||||||
CURLOPT_INFILE
|
|
||||||
CURLOPT_INFILESIZE
|
|
||||||
CURLOPT_INTERFACE
|
|
||||||
CURLOPT_KRB4LEVEL
|
|
||||||
CURLOPT_LOW_SPEED_LIMIT
|
|
||||||
CURLOPT_LOW_SPEED_TIME
|
|
||||||
CURLOPT_MAXCONNECTS
|
|
||||||
CURLOPT_MAXREDIRS
|
|
||||||
CURLOPT_MUTE
|
|
||||||
CURLOPT_NETRC
|
|
||||||
CURLOPT_NOBODY
|
|
||||||
CURLOPT_NOPROGRESS
|
|
||||||
CURLOPT_NOTHING
|
|
||||||
CURLOPT_PASSWDDATA
|
|
||||||
CURLOPT_PASSWDFUNCTION
|
|
||||||
CURLOPT_PORT
|
|
||||||
CURLOPT_POST
|
|
||||||
CURLOPT_POSTFIELDS
|
|
||||||
CURLOPT_POSTFIELDSIZE
|
|
||||||
CURLOPT_POSTQUOTE
|
|
||||||
CURLOPT_PROGRESSDATA
|
|
||||||
CURLOPT_PROGRESSFUNCTION
|
|
||||||
CURLOPT_PROXY
|
|
||||||
CURLOPT_PROXYPORT
|
|
||||||
CURLOPT_PROXYUSERPWD
|
|
||||||
CURLOPT_PUT
|
|
||||||
CURLOPT_QUOTE
|
|
||||||
CURLOPT_RANDOM_FILE
|
|
||||||
CURLOPT_RANGE
|
|
||||||
CURLOPT_READFUNCTION
|
|
||||||
CURLOPT_REFERER
|
|
||||||
CURLOPT_RESUME_FROM
|
|
||||||
CURLOPT_SSLCERT
|
|
||||||
CURLOPT_SSLCERTPASSWD
|
|
||||||
CURLOPT_SSLVERSION
|
|
||||||
CURLOPT_SSL_CIPHER_LIST
|
|
||||||
CURLOPT_SSL_VERIFYHOST
|
|
||||||
CURLOPT_SSL_VERIFYPEER
|
|
||||||
CURLOPT_STDERR
|
|
||||||
CURLOPT_TELNETOPTIONS
|
|
||||||
CURLOPT_TIMECONDITION
|
|
||||||
CURLOPT_TIMEOUT
|
|
||||||
CURLOPT_TIMEVALUE
|
|
||||||
CURLOPT_TRANSFERTEXT
|
|
||||||
CURLOPT_UPLOAD
|
|
||||||
CURLOPT_URL
|
|
||||||
CURLOPT_USERAGENT
|
|
||||||
CURLOPT_USERPWD
|
|
||||||
CURLOPT_VERBOSE
|
|
||||||
CURLOPT_WRITEFUNCTION
|
|
||||||
CURLOPT_WRITEHEADER
|
|
||||||
CURLOPT_WRITEINFO
|
|
||||||
|
|
||||||
CURLINFO_EFFECTIVE_URL
|
|
||||||
CURLINFO_HTTP_CODE
|
|
||||||
CURLINFO_TOTAL_TIME
|
|
||||||
CURLINFO_NAMELOOKUP_TIME
|
|
||||||
CURLINFO_CONNECT_TIME
|
|
||||||
CURLINFO_PRETRANSFER_TIME
|
|
||||||
CURLINFO_SIZE_UPLOAD
|
|
||||||
CURLINFO_SIZE_DOWNLOAD
|
|
||||||
CURLINFO_SPEED_DOWNLOAD
|
|
||||||
CURLINFO_SPEED_UPLOAD
|
|
||||||
CURLINFO_HEADER_SIZE
|
|
||||||
CURLINFO_REQUEST_SIZE
|
|
||||||
CURLINFO_SSL_VERIFYRESULT
|
|
||||||
CURLINFO_FILETIME
|
|
||||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD
|
|
||||||
CURLINFO_CONTENT_LENGTH_UPLOAD
|
|
||||||
|
|
||||||
USE_INTERNAL_VARS
|
|
||||||
);
|
|
||||||
|
|
||||||
$VERSION = '1.1.8';
|
|
||||||
|
|
||||||
$Curl::easy::headers = "";
|
|
||||||
$Curl::easy::content = "";
|
|
||||||
|
|
||||||
sub AUTOLOAD {
|
|
||||||
# This AUTOLOAD is used to 'autoload' constants from the constant()
|
|
||||||
# XS function.
|
|
||||||
|
|
||||||
(my $constname = $AUTOLOAD) =~ s/.*:://;
|
|
||||||
return constant($constname, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bootstrap Curl::easy $VERSION;
|
|
||||||
|
|
||||||
# Preloaded methods go here.
|
|
||||||
|
|
||||||
# Autoload methods go after =cut, and are processed by the autosplit program.
|
|
||||||
|
|
||||||
1;
|
|
||||||
__END__
|
|
||||||
# Below is the stub of documentation for your module. You better edit it!
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
Curl::easy - Perl extension for libcurl
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$curl = Curl::easy::init();
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLoption, Value);
|
|
||||||
$CURLcode = Curl::easy::perform($curl);
|
|
||||||
Curl::easy::cleanup($curl);
|
|
||||||
|
|
||||||
Read curl_easy_setopt for details of most CURLoption values
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
B<Curl::easy> provides an interface to the libcurl C library. See
|
|
||||||
http://curl.haxx.se/ for more information on cURL and libcurl.
|
|
||||||
|
|
||||||
=head2 FILES and CALLBACKS
|
|
||||||
|
|
||||||
Curl::easy supports the various options of curl_easy_setopt which require either a FILE * or
|
|
||||||
a callback function.
|
|
||||||
|
|
||||||
The perl callback functions are handled through a C wrapper which takes care of converting
|
|
||||||
from C to perl variables and back again. This wrapper simplifies some C arguments to make
|
|
||||||
them behave in a more 'perl' like manner. In particular, the read and write callbacks do not
|
|
||||||
look just like the 'fread' and 'fwrite' C functions - perl variables do not need separate length
|
|
||||||
parameters, and perl functions can return a list of variables, instead of needing a pointer
|
|
||||||
to modify. The details are described below.
|
|
||||||
|
|
||||||
=head2 FILE handles (GLOBS)
|
|
||||||
|
|
||||||
Curl options which take a FILE, such as CURLOPT_FILE, CURLOPT_WRITEHEADER, CURLOPT_INFILE
|
|
||||||
can be passed a perl file handle:
|
|
||||||
|
|
||||||
open BODY,">body.out";
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, BODY);
|
|
||||||
|
|
||||||
=head2 WRITE callback
|
|
||||||
|
|
||||||
The CUROPT_WRITEFUNCTION option may be set which will cause libcurl to callback to
|
|
||||||
the given subroutine:
|
|
||||||
|
|
||||||
sub chunk { my ($data,$pointer)=@_; ...; return length($data) }
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, \&chunk );
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, );
|
|
||||||
|
|
||||||
In this case, the subroutine will be passed whatever is defined by CURLOPT_FILE. This can be
|
|
||||||
a ref to a scalar, or a GLOB or anything else you like.
|
|
||||||
|
|
||||||
The callback function must return the number of bytes 'handled' ( length($data) ) or the transfer
|
|
||||||
will abort. A transfer can be aborted by returning a 'length' of '-1'.
|
|
||||||
|
|
||||||
The option CURLOPT_WRITEHEADER can be set to pass a different '$pointer' into the CURLOPT_WRITEFUNCTION
|
|
||||||
for header values. This lets you collect the headers and body separately:
|
|
||||||
|
|
||||||
my $headers="";
|
|
||||||
my $body="";
|
|
||||||
sub chunk { my ($data,$pointer)=@_; ${$pointer}.=$data; return length($data) }
|
|
||||||
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, \&chunk );
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, \$header );
|
|
||||||
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, \$body );
|
|
||||||
|
|
||||||
If you have libcurl > 7.7.1, then you could instead set CURLOPT_HEADERFUNCTION to a different callback,
|
|
||||||
and have the header collected that way.
|
|
||||||
|
|
||||||
=head2 READ callback
|
|
||||||
|
|
||||||
Curl::easy supports CURLOPT_READFUNCTION. This function should look something like this:
|
|
||||||
|
|
||||||
sub read_callback {
|
|
||||||
my ($maxlength,$pointer)=@_;
|
|
||||||
|
|
||||||
....
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
The subroutine must return an empty string "" at the end of the data. Note that this function
|
|
||||||
isn't told how much data to provide - $maxlength is just the maximum size of the buffer
|
|
||||||
provided by libcurl. If you are doing an HTTP POST or PUT for example, it is important that this
|
|
||||||
function only returns as much data as the 'Content-Length' header specifies, followed by a
|
|
||||||
an empty (0 length) buffer.
|
|
||||||
|
|
||||||
=head2 PROGRESS callback
|
|
||||||
|
|
||||||
Curl::easy supports CURLOPT_PROGRESSFUNCTION. This function should look something like this:
|
|
||||||
|
|
||||||
sub prog_callb
|
|
||||||
{
|
|
||||||
my ($clientp,$dltotal,$dlnow,$ultotal,$ulnow)=@_;
|
|
||||||
....
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
The function should return 0 normally, or -1 which will abort/cancel the transfer. $clientp is whatever
|
|
||||||
value/scalar is set using the CURLOPT_PROGRESSDATA option.
|
|
||||||
|
|
||||||
=head2 PASSWD callback
|
|
||||||
|
|
||||||
Curl::easy supports CURLOPT_PASSWDFUNCTION. This function should look something like this:
|
|
||||||
|
|
||||||
sub passwd_callb
|
|
||||||
{
|
|
||||||
my ($clientp,$prompt,$buflen)=@_;
|
|
||||||
...
|
|
||||||
return (0,$data);
|
|
||||||
}
|
|
||||||
|
|
||||||
$clientp is whatever scalar is set using the CURLOPT_PASSWDDATA option.
|
|
||||||
$prompt is a text string which can be used to prompt for a password.
|
|
||||||
$buflen is the maximum accepted password reply.
|
|
||||||
|
|
||||||
The function must return 0 (for 'OK') and the password data as a list. Return (-1,"") to
|
|
||||||
indicate an error.
|
|
||||||
|
|
||||||
=head1 AUTHOR
|
|
||||||
|
|
||||||
Georg Horn <horn@koblenz-net.de>
|
|
||||||
|
|
||||||
Additional callback, pod and test work by Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
and Forrest Cahoon <forrest.cahoon@merrillcorp.com>
|
|
||||||
|
|
||||||
Currently maintained by Cris Bailiff <c.bailiff@devsecure.com>
|
|
||||||
|
|
||||||
=head1 Copyright
|
|
||||||
|
|
||||||
Copyright (C) 2000, Daniel Stenberg, , et al.
|
|
||||||
|
|
||||||
You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
||||||
copies of the Software, and permit persons to whom the Software is furnished
|
|
||||||
to do so, under the terms of the MPL or the MIT/X-derivate licenses. You may
|
|
||||||
pick one of these licenses.
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
http://curl.haxx.se/
|
|
||||||
|
|
||||||
=cut
|
|
@@ -1,672 +0,0 @@
|
|||||||
/* Perl interface for libcurl. Check out the file README for more info. */
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (C) 2000, Daniel Stenberg, , et al.
|
|
||||||
You may opt to use, copy, modify, merge, publish, distribute and/or
|
|
||||||
sell copies of the Software, and permit persons to whom the
|
|
||||||
Software is furnished to do so, under the terms of the MPL or
|
|
||||||
the MIT/X-derivate licenses. You may pick one of these licenses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EXTERN.h"
|
|
||||||
#include "perl.h"
|
|
||||||
#include "XSUB.h"
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <curl/easy.h>
|
|
||||||
|
|
||||||
#if (LIBCURL_VERSION_NUM<0x070702)
|
|
||||||
#define CURLOPT_HEADERFUNCTION 20079
|
|
||||||
#define header_callback_func write_callback_func
|
|
||||||
#else
|
|
||||||
#define header_callback_func writeheader_callback_func
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Lists that can be set via curl_easy_setopt() */
|
|
||||||
|
|
||||||
static struct curl_slist *httpheader = NULL, *quote = NULL, *postquote = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/* Buffer and varname for option CURLOPT_ERRORBUFFER */
|
|
||||||
|
|
||||||
static char errbuf[CURL_ERROR_SIZE];
|
|
||||||
static char *errbufvarname = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/* Callback functions */
|
|
||||||
|
|
||||||
static SV *read_callback = NULL, *write_callback = NULL,
|
|
||||||
*progress_callback = NULL, *passwd_callback = NULL,
|
|
||||||
*header_callback = NULL;
|
|
||||||
/* *closepolicy_callback = NULL; */
|
|
||||||
|
|
||||||
|
|
||||||
/* For storing the content */
|
|
||||||
|
|
||||||
static char *contbuf = NULL, *bufptr = NULL;
|
|
||||||
static int bufsize = 32768, contlen = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal options for this perl module */
|
|
||||||
|
|
||||||
#define USE_INTERNAL_VARS 0x01
|
|
||||||
|
|
||||||
static int internal_options = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup these global vars */
|
|
||||||
|
|
||||||
static void init_globals(void)
|
|
||||||
{
|
|
||||||
if (httpheader) curl_slist_free_all(httpheader);
|
|
||||||
if (quote) curl_slist_free_all(quote);
|
|
||||||
if (postquote) curl_slist_free_all(postquote);
|
|
||||||
httpheader = quote = postquote = NULL;
|
|
||||||
if (errbufvarname) free(errbufvarname);
|
|
||||||
errbufvarname = NULL;
|
|
||||||
if (contbuf == NULL) {
|
|
||||||
contbuf = malloc(bufsize + 1);
|
|
||||||
}
|
|
||||||
bufptr = contbuf;
|
|
||||||
*bufptr = '\0';
|
|
||||||
contlen = 0;
|
|
||||||
internal_options = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Register a callback function */
|
|
||||||
|
|
||||||
static void register_callback(SV **callback, SV *function)
|
|
||||||
{
|
|
||||||
if (*callback == NULL) {
|
|
||||||
/* First time, create new SV */
|
|
||||||
*callback = newSVsv(function);
|
|
||||||
} else {
|
|
||||||
/* Been there, done that. Just overwrite the SV */
|
|
||||||
SvSetSV(*callback, function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generic fwrite callback, which decides which callback to call */
|
|
||||||
static size_t
|
|
||||||
fwrite_wrapper (const void *ptr,
|
|
||||||
size_t size,
|
|
||||||
size_t nmemb,
|
|
||||||
void *stream,
|
|
||||||
void *call_function)
|
|
||||||
{
|
|
||||||
dSP;
|
|
||||||
int count, status;
|
|
||||||
SV *sv;
|
|
||||||
|
|
||||||
if (call_function) {
|
|
||||||
/* then we are doing a callback to perl */
|
|
||||||
|
|
||||||
ENTER;
|
|
||||||
SAVETMPS;
|
|
||||||
|
|
||||||
PUSHMARK(SP);
|
|
||||||
|
|
||||||
if (stream == stdout) {
|
|
||||||
sv = newSViv(0); /* FIXME: should cast stdout to GLOB somehow? */
|
|
||||||
} else if (stream == NULL) {
|
|
||||||
sv = &PL_sv_undef;
|
|
||||||
} else { /* its already an SV */
|
|
||||||
sv = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr != NULL) {
|
|
||||||
XPUSHs(sv_2mortal(newSVpvn((char *)ptr, (STRLEN)(size * nmemb))));
|
|
||||||
} else {
|
|
||||||
XPUSHs(sv_2mortal(newSVpv("", 0)));
|
|
||||||
}
|
|
||||||
XPUSHs(sv_2mortal(newSVsv(sv))); /* CURLOPT_FILE SV* */
|
|
||||||
PUTBACK;
|
|
||||||
|
|
||||||
count = perl_call_sv((SV *) call_function, G_SCALAR);
|
|
||||||
|
|
||||||
SPAGAIN;
|
|
||||||
if (count != 1)
|
|
||||||
croak("Big trouble, perl_call_sv(write_callback) didn't return status\n");
|
|
||||||
|
|
||||||
status = POPi;
|
|
||||||
|
|
||||||
PUTBACK;
|
|
||||||
|
|
||||||
FREETMPS;
|
|
||||||
LEAVE;
|
|
||||||
return status;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* default to a normal 'fwrite' */
|
|
||||||
/* stream could be a FILE * or an SV * */
|
|
||||||
/* or NULL since libcurl-7.8.1pre3 */
|
|
||||||
FILE *f;
|
|
||||||
|
|
||||||
if (stream == stdout ||
|
|
||||||
stream == NULL) { /* the only possible FILE ? Think so */
|
|
||||||
f = stream;
|
|
||||||
} else { /* its a GLOB */
|
|
||||||
f = IoIFP(sv_2io(stream)); /* may barf if not a GLOB */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f)
|
|
||||||
return fwrite(ptr, size, nmemb, f);
|
|
||||||
else
|
|
||||||
return (size_t) size*nmemb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write callback for calling a perl callback */
|
|
||||||
size_t
|
|
||||||
write_callback_func( const void *ptr, size_t size,
|
|
||||||
size_t nmemb, void *stream)
|
|
||||||
{
|
|
||||||
return fwrite_wrapper(ptr,size,nmemb,stream,
|
|
||||||
write_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* header callback for calling a perl callback */
|
|
||||||
size_t
|
|
||||||
writeheader_callback_func( const void *ptr, size_t size,
|
|
||||||
size_t nmemb, void *stream)
|
|
||||||
{
|
|
||||||
return fwrite_wrapper(ptr,size,nmemb,stream,
|
|
||||||
header_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
read_callback_func( void *ptr, size_t size,
|
|
||||||
size_t nmemb, void *stream)
|
|
||||||
{
|
|
||||||
dSP ;
|
|
||||||
|
|
||||||
int count;
|
|
||||||
SV *sv;
|
|
||||||
STRLEN len;
|
|
||||||
size_t maxlen,mylen;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
maxlen = size*nmemb;
|
|
||||||
|
|
||||||
if (read_callback) {
|
|
||||||
/* we are doing a callback to perl */
|
|
||||||
|
|
||||||
ENTER ;
|
|
||||||
SAVETMPS ;
|
|
||||||
|
|
||||||
PUSHMARK(SP) ;
|
|
||||||
|
|
||||||
if (stream == stdin) {
|
|
||||||
sv = newSViv(0); /* should cast stdin to GLOB somehow? */
|
|
||||||
} else { /* its an SV */
|
|
||||||
sv = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
XPUSHs(sv_2mortal(newSViv(maxlen))); /* send how many bytes please */
|
|
||||||
XPUSHs(sv_2mortal(newSVsv(sv))); /* CURLOPT_INFILE SV* */
|
|
||||||
PUTBACK ;
|
|
||||||
|
|
||||||
count = perl_call_sv(read_callback, G_SCALAR);
|
|
||||||
|
|
||||||
SPAGAIN;
|
|
||||||
if (count != 1)
|
|
||||||
croak("Big trouble, perl_call_sv(read_callback) didn't return data\n");
|
|
||||||
|
|
||||||
sv = POPs;
|
|
||||||
p = SvPV(sv,len);
|
|
||||||
|
|
||||||
/* only allowed to return the number of bytes asked for */
|
|
||||||
mylen = len<maxlen ? len : maxlen;
|
|
||||||
memcpy(ptr,p,(size_t)mylen);
|
|
||||||
PUTBACK ;
|
|
||||||
|
|
||||||
FREETMPS ;
|
|
||||||
LEAVE ;
|
|
||||||
return (size_t) (mylen/size);
|
|
||||||
} else {
|
|
||||||
/* default to a normal 'fread' */
|
|
||||||
/* stream could be a FILE * or an SV * */
|
|
||||||
FILE *f;
|
|
||||||
|
|
||||||
if (stream == stdin) { /* the only possible FILE ? Think so*/
|
|
||||||
f = stream;
|
|
||||||
} else { /* its a GLOB */
|
|
||||||
f = IoIFP(sv_2io(stream)); /* may barf if not a GLOB */
|
|
||||||
}
|
|
||||||
|
|
||||||
return fread(ptr,size,nmemb,f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Porgress callback for calling a perl callback */
|
|
||||||
|
|
||||||
static int progress_callback_func(void *clientp, size_t dltotal, size_t dlnow,
|
|
||||||
size_t ultotal, size_t ulnow)
|
|
||||||
{
|
|
||||||
dSP;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
ENTER;
|
|
||||||
SAVETMPS;
|
|
||||||
PUSHMARK(sp);
|
|
||||||
if (clientp != NULL) {
|
|
||||||
XPUSHs(sv_2mortal(newSVpv(clientp, 0)));
|
|
||||||
} else {
|
|
||||||
XPUSHs(sv_2mortal(newSVpv("", 0)));
|
|
||||||
}
|
|
||||||
XPUSHs(sv_2mortal(newSViv(dltotal)));
|
|
||||||
XPUSHs(sv_2mortal(newSViv(dlnow)));
|
|
||||||
XPUSHs(sv_2mortal(newSViv(ultotal)));
|
|
||||||
XPUSHs(sv_2mortal(newSViv(ulnow)));
|
|
||||||
PUTBACK;
|
|
||||||
count = perl_call_sv(progress_callback, G_SCALAR);
|
|
||||||
SPAGAIN;
|
|
||||||
if (count != 1)
|
|
||||||
croak("Big trouble, perl_call_sv(progress_callback) didn't return 1\n");
|
|
||||||
count = POPi;
|
|
||||||
PUTBACK;
|
|
||||||
FREETMPS;
|
|
||||||
LEAVE;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Password callback for calling a perl callback */
|
|
||||||
|
|
||||||
static int passwd_callback_func(void *clientp, char *prompt, char *buffer,
|
|
||||||
int buflen)
|
|
||||||
{
|
|
||||||
dSP;
|
|
||||||
int count;
|
|
||||||
SV *sv;
|
|
||||||
STRLEN len;
|
|
||||||
size_t mylen;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
ENTER;
|
|
||||||
SAVETMPS;
|
|
||||||
PUSHMARK(sp);
|
|
||||||
if (clientp != NULL) {
|
|
||||||
XPUSHs(sv_2mortal(newSVsv(clientp)));
|
|
||||||
} else {
|
|
||||||
XPUSHs(sv_2mortal(newSVpv("", 0)));
|
|
||||||
}
|
|
||||||
XPUSHs(sv_2mortal(newSVpv(prompt, 0)));
|
|
||||||
XPUSHs(sv_2mortal(newSViv(buflen)));
|
|
||||||
PUTBACK;
|
|
||||||
count = perl_call_sv(passwd_callback, G_ARRAY);
|
|
||||||
SPAGAIN;
|
|
||||||
if (count != 2)
|
|
||||||
croak("Big trouble, perl_call_sv(passwd_callback) didn't return status + data\n");
|
|
||||||
|
|
||||||
sv = POPs;
|
|
||||||
count = POPi;
|
|
||||||
|
|
||||||
p = SvPV(sv,len);
|
|
||||||
|
|
||||||
/* only allowed to return the number of bytes asked for */
|
|
||||||
mylen = len<(buflen-1) ? len : (buflen-1);
|
|
||||||
memcpy(buffer,p,mylen);
|
|
||||||
buffer[buflen]=0; /* ensure C string terminates */
|
|
||||||
|
|
||||||
PUTBACK;
|
|
||||||
FREETMPS;
|
|
||||||
LEAVE;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* awaiting closepolicy prototype */
|
|
||||||
int
|
|
||||||
closepolicy_callback_func(void *clientp)
|
|
||||||
{
|
|
||||||
dSP;
|
|
||||||
int argc, status;
|
|
||||||
SV *pl_status;
|
|
||||||
|
|
||||||
ENTER;
|
|
||||||
SAVETMPS;
|
|
||||||
|
|
||||||
PUSHMARK(SP);
|
|
||||||
PUTBACK;
|
|
||||||
|
|
||||||
argc = perl_call_sv(closepolicy_callback, G_SCALAR);
|
|
||||||
SPAGAIN;
|
|
||||||
|
|
||||||
if (argc != 1) {
|
|
||||||
croak("Unexpected number of arguments returned from closefunction callback\n");
|
|
||||||
}
|
|
||||||
pl_status = POPs;
|
|
||||||
status = SvTRUE(pl_status) ? 0 : 1;
|
|
||||||
|
|
||||||
PUTBACK;
|
|
||||||
FREETMPS;
|
|
||||||
LEAVE;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal write callback. Only used if USE_INTERNAL_VARS was specified */
|
|
||||||
|
|
||||||
static size_t internal_write_callback(char *data, size_t size, size_t num,
|
|
||||||
FILE *fp)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
size *= num;
|
|
||||||
if ((contlen + size) >= bufsize) {
|
|
||||||
bufsize *= 2;
|
|
||||||
contbuf = realloc(contbuf, bufsize + 1);
|
|
||||||
bufptr = contbuf + contlen;
|
|
||||||
}
|
|
||||||
contlen += size;
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
*bufptr++ = *data++;
|
|
||||||
}
|
|
||||||
*bufptr = '\0';
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
constant(char *name, int arg)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
if (strncmp(name, "CURLINFO_", 9) == 0) {
|
|
||||||
name += 9;
|
|
||||||
switch (*name) {
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
if (strEQ(name, "CONNECT_TIME")) return CURLINFO_CONNECT_TIME;
|
|
||||||
if (strEQ(name, "CONTENT_LENGTH_DOWNLOAD")) return CURLINFO_CONTENT_LENGTH_DOWNLOAD;
|
|
||||||
if (strEQ(name, "CONTENT_LENGTH_UPLOAD")) return CURLINFO_CONTENT_LENGTH_UPLOAD;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
if (strEQ(name, "EFFECTIVE_URL")) return CURLINFO_EFFECTIVE_URL;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
if (strEQ(name, "FILETIME")) return CURLINFO_FILETIME;
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
case 'H':
|
|
||||||
if (strEQ(name, "HEADER_SIZE")) return CURLINFO_HEADER_SIZE;
|
|
||||||
if (strEQ(name, "HTTP_CODE")) return CURLINFO_HTTP_CODE;
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
case 'J':
|
|
||||||
case 'K':
|
|
||||||
case 'L':
|
|
||||||
case 'M':
|
|
||||||
case 'N':
|
|
||||||
if (strEQ(name, "NAMELOOKUP_TIME")) return CURLINFO_NAMELOOKUP_TIME;
|
|
||||||
break;
|
|
||||||
case 'O':
|
|
||||||
case 'P':
|
|
||||||
if (strEQ(name, "PRETRANSFER_TIME")) return CURLINFO_PRETRANSFER_TIME;
|
|
||||||
break;
|
|
||||||
case 'Q':
|
|
||||||
case 'R':
|
|
||||||
if (strEQ(name, "REQUEST_SIZE")) return CURLINFO_REQUEST_SIZE;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
if (strEQ(name, "SSL_VERIFYRESULT")) return CURLINFO_SSL_VERIFYRESULT;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
if (strEQ(name, "SIZE_DOWNLOAD")) return CURLINFO_SIZE_DOWNLOAD;
|
|
||||||
if (strEQ(name, "SIZE_UPLOAD")) return CURLINFO_SIZE_UPLOAD;
|
|
||||||
if (strEQ(name, "SPEED_DOWNLOAD")) return CURLINFO_SPEED_DOWNLOAD;
|
|
||||||
if (strEQ(name, "SPEED_UPLOAD")) return CURLINFO_SPEED_UPLOAD;
|
|
||||||
if (strEQ(name, "TOTAL_TIME")) return CURLINFO_TOTAL_TIME;
|
|
||||||
break;
|
|
||||||
case 'U':
|
|
||||||
case 'V':
|
|
||||||
case 'W':
|
|
||||||
case 'X':
|
|
||||||
case 'Y':
|
|
||||||
case 'Z':
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strncmp(name, "CURLOPT_", 8) == 0) {
|
|
||||||
name += 8;
|
|
||||||
switch (*name) {
|
|
||||||
#include "curlopt-constants.c"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strEQ(name, "USE_INTERNAL_VARS")) return USE_INTERNAL_VARS;
|
|
||||||
errno = EINVAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MODULE = Curl::easy PACKAGE = Curl::easy PREFIX = curl_easy_
|
|
||||||
|
|
||||||
int
|
|
||||||
constant(name,arg)
|
|
||||||
char * name
|
|
||||||
int arg
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
curl_easy_init()
|
|
||||||
CODE:
|
|
||||||
init_globals();
|
|
||||||
RETVAL = curl_easy_init();
|
|
||||||
curl_easy_setopt(RETVAL, CURLOPT_HEADERFUNCTION, header_callback_func);
|
|
||||||
curl_easy_setopt(RETVAL, CURLOPT_WRITEFUNCTION, write_callback_func);
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
char *
|
|
||||||
curl_easy_version()
|
|
||||||
CODE:
|
|
||||||
RETVAL=curl_version();
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
int
|
|
||||||
curl_easy_setopt(curl, option, value)
|
|
||||||
void * curl
|
|
||||||
int option
|
|
||||||
SV * value
|
|
||||||
CODE:
|
|
||||||
if (option < CURLOPTTYPE_OBJECTPOINT) {
|
|
||||||
/* This is an option specifying an integer value: */
|
|
||||||
RETVAL = curl_easy_setopt(curl, option, (long)SvIV(value));
|
|
||||||
} else if (option == CURLOPT_FILE || option == CURLOPT_INFILE ||
|
|
||||||
option == CURLOPT_WRITEHEADER || option == CURLOPT_PROGRESSDATA ||
|
|
||||||
option == CURLOPT_PASSWDDATA) {
|
|
||||||
/* This is an option specifying an SV * value: */
|
|
||||||
RETVAL = curl_easy_setopt(curl, option, newSVsv(ST(2)));
|
|
||||||
} else if (option == CURLOPT_ERRORBUFFER) {
|
|
||||||
/* Pass in variable name for storing error messages... */
|
|
||||||
RETVAL = curl_easy_setopt(curl, option, errbuf);
|
|
||||||
if (errbufvarname) free(errbufvarname);
|
|
||||||
errbufvarname = strdup((char *)SvPV(value, PL_na));
|
|
||||||
} else if (option == CURLOPT_WRITEFUNCTION || option ==
|
|
||||||
CURLOPT_READFUNCTION || option == CURLOPT_PROGRESSFUNCTION ||
|
|
||||||
option == CURLOPT_PASSWDFUNCTION || option == CURLOPT_HEADERFUNCTION) {
|
|
||||||
/* This is an option specifying a callback function */
|
|
||||||
switch (option) {
|
|
||||||
case CURLOPT_WRITEFUNCTION:
|
|
||||||
register_callback(&write_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_func);
|
|
||||||
break;
|
|
||||||
case CURLOPT_READFUNCTION:
|
|
||||||
register_callback(&read_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback_func);
|
|
||||||
break;
|
|
||||||
case CURLOPT_HEADERFUNCTION:
|
|
||||||
register_callback(&header_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback_func);
|
|
||||||
case CURLOPT_PROGRESSFUNCTION:
|
|
||||||
register_callback(&progress_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback_func);
|
|
||||||
break;
|
|
||||||
case CURLOPT_PASSWDFUNCTION:
|
|
||||||
register_callback(&passwd_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_PASSWDFUNCTION, passwd_callback_func);
|
|
||||||
break;
|
|
||||||
/* awaiting a prototype for the closepolicy function callback
|
|
||||||
case CURLOPT_CLOSEFUNCTION:
|
|
||||||
register_callback(&closepolicy_callback, value);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_CLOSEFUNCTION, closepolicy_callback_func);
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
RETVAL = -1;
|
|
||||||
} else if (option == CURLOPT_HTTPHEADER || option == CURLOPT_QUOTE ||
|
|
||||||
option == CURLOPT_POSTQUOTE) {
|
|
||||||
/* This is an option specifying a list of curl_slist structs: */
|
|
||||||
AV *array = (AV *)SvRV(value);
|
|
||||||
struct curl_slist **slist = NULL;
|
|
||||||
/* We have to find out which list to use... */
|
|
||||||
switch (option) {
|
|
||||||
case CURLOPT_HTTPHEADER:
|
|
||||||
slist = &httpheader; break;
|
|
||||||
case CURLOPT_QUOTE:
|
|
||||||
slist = "e; break;
|
|
||||||
case CURLOPT_POSTQUOTE:
|
|
||||||
slist = &postquote; break;
|
|
||||||
}
|
|
||||||
/* free any previous list */
|
|
||||||
if (*slist) {
|
|
||||||
curl_slist_free_all(*slist);
|
|
||||||
*slist=NULL;
|
|
||||||
}
|
|
||||||
/* ...store the values into it... */
|
|
||||||
for (;;) {
|
|
||||||
SV *sv = av_shift(array);
|
|
||||||
int len = 0;
|
|
||||||
char *str = SvPV(sv, len);
|
|
||||||
if (len == 0) break;
|
|
||||||
*slist = curl_slist_append(*slist, str);
|
|
||||||
}
|
|
||||||
/* ...and pass the list into curl_easy_setopt() */
|
|
||||||
RETVAL = curl_easy_setopt(curl, option, *slist);
|
|
||||||
} else {
|
|
||||||
/* This is an option specifying a char * value: */
|
|
||||||
RETVAL = curl_easy_setopt(curl, option, SvPV(value, PL_na));
|
|
||||||
}
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
internal_setopt(option, value)
|
|
||||||
int option
|
|
||||||
int value
|
|
||||||
CODE:
|
|
||||||
if (value == 1) {
|
|
||||||
internal_options |= option;
|
|
||||||
} else {
|
|
||||||
internal_options &= !option;
|
|
||||||
}
|
|
||||||
RETVAL = 0;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
curl_easy_perform(curl)
|
|
||||||
void * curl
|
|
||||||
CODE:
|
|
||||||
if (internal_options & USE_INTERNAL_VARS) {
|
|
||||||
/* Use internal callback which just stores the content into a buffer. */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, internal_write_callback);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
|
|
||||||
}
|
|
||||||
RETVAL = curl_easy_perform(curl);
|
|
||||||
if (RETVAL && errbufvarname) {
|
|
||||||
/* If an error occurred and a varname for error messages has been
|
|
||||||
specified, store the error message. */
|
|
||||||
SV *sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI);
|
|
||||||
sv_setpv(sv, errbuf);
|
|
||||||
}
|
|
||||||
if (!RETVAL && (internal_options & USE_INTERNAL_VARS)) {
|
|
||||||
/* No error and internal variable for the content are to be used:
|
|
||||||
Split the data into headers and content and store them into
|
|
||||||
perl variables. */
|
|
||||||
SV *head_sv = perl_get_sv("Curl::easy::headers", TRUE | GV_ADDMULTI);
|
|
||||||
SV *cont_sv = perl_get_sv("Curl::easy::content", TRUE | GV_ADDMULTI);
|
|
||||||
char *p = contbuf;
|
|
||||||
int nl = 0, found = 0;
|
|
||||||
while (p < bufptr) {
|
|
||||||
if (nl && (*p == '\n' || *p == '\r')) {
|
|
||||||
/* found empty line, end of headers */
|
|
||||||
*p++ = '\0';
|
|
||||||
sv_setpv(head_sv, contbuf);
|
|
||||||
while (*p == '\n' || *p == '\r') {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
sv_setpv(cont_sv, p);
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nl = (*p == '\n');
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
sv_setpv(head_sv, "");
|
|
||||||
sv_setpv(cont_sv, contbuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
curl_easy_getinfo(curl, option, value)
|
|
||||||
void * curl
|
|
||||||
int option
|
|
||||||
double value
|
|
||||||
CODE:
|
|
||||||
#ifdef __GNUC__
|
|
||||||
/* a(void) warnig about unnused variable */
|
|
||||||
(void) value;
|
|
||||||
#endif
|
|
||||||
switch (option & CURLINFO_TYPEMASK) {
|
|
||||||
case CURLINFO_STRING: {
|
|
||||||
char * value = (char *)SvPV(ST(2), PL_na);
|
|
||||||
RETVAL = curl_easy_getinfo(curl, option, &value);
|
|
||||||
sv_setpv(ST(2), value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CURLINFO_LONG: {
|
|
||||||
long value = (long)SvIV(ST(2));
|
|
||||||
RETVAL = curl_easy_getinfo(curl, option, &value);
|
|
||||||
sv_setiv(ST(2), value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CURLINFO_DOUBLE: {
|
|
||||||
double value = (double)SvNV(ST(2));
|
|
||||||
RETVAL = curl_easy_getinfo(curl, option, &value);
|
|
||||||
sv_setnv(ST(2), value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
RETVAL = CURLE_BAD_FUNCTION_ARGUMENT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
curl_easy_cleanup(curl)
|
|
||||||
void * curl
|
|
||||||
CODE:
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
init_globals();
|
|
||||||
RETVAL = 0;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
@@ -1,48 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
my $url = "http://curl.haxx.se/dev/";
|
|
||||||
|
|
||||||
print "Testing curl version ",&Curl::easy::version(),"\n";
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl= Curl::easy::init();
|
|
||||||
if(!$curl) {
|
|
||||||
die "curl init failed!\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Follow location headers
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
|
|
||||||
# Add some additional headers to the http-request:
|
|
||||||
my @myheaders;
|
|
||||||
$myheaders[0] = "I-am-a-silly-programmer: yes indeed you are";
|
|
||||||
$myheaders[1] = "User-Agent: Perl interface for libcURL";
|
|
||||||
Curl::easy::setopt($curl, Curl::easy::CURLOPT_HTTPHEADER, \@myheaders);
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
sub body_callback {
|
|
||||||
my ($chunk,$handle)=@_;
|
|
||||||
push @$handle, $chunk;
|
|
||||||
return length($chunk); # OK
|
|
||||||
}
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, \&body_callback);
|
|
||||||
|
|
||||||
my @body;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE, \@body);
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) != 0) {
|
|
||||||
print "Failed :$errbuf\n";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
Curl::easy::cleanup($curl);
|
|
||||||
|
|
||||||
print @body;
|
|
@@ -1,38 +0,0 @@
|
|||||||
|
|
||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make test'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
# (It may become useful if the test is moved to ./t subdirectory.)
|
|
||||||
use Benchmark;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..2\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################## End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
print STDERR "Testing curl version ",&Curl::easy::version(),"\n";
|
|
||||||
|
|
||||||
if (CURLOPT_URL != 10000+2) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "ok ".++$count;
|
|
||||||
|
|
||||||
exit;
|
|
@@ -1,93 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..6\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
# Add some additional headers to the http-request:
|
|
||||||
my @myheaders;
|
|
||||||
$myheaders[0] = "Server: www";
|
|
||||||
$myheaders[1] = "User-Agent: Perl interface for libcURL";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_HTTPHEADER, \@myheaders);
|
|
||||||
|
|
||||||
my $bytes;
|
|
||||||
my $realurl;
|
|
||||||
my $httpcode;
|
|
||||||
|
|
||||||
# Go get it
|
|
||||||
my $retcode=Curl::easy::perform($curl);
|
|
||||||
if ($retcode == 0) {
|
|
||||||
Curl::easy::getinfo($curl, CURLINFO_SIZE_DOWNLOAD, $bytes);
|
|
||||||
print STDERR "$bytes bytes read ";
|
|
||||||
Curl::easy::getinfo($curl, CURLINFO_EFFECTIVE_URL, $realurl);
|
|
||||||
Curl::easy::getinfo($curl, CURLINFO_HTTP_CODE, $httpcode);
|
|
||||||
print STDERR "effective fetched url (http code: $httpcode) was: $url ";
|
|
||||||
} else {
|
|
||||||
# We can acces the error message in $errbuf here
|
|
||||||
print STDERR "$retcode / '$errbuf'\n";
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
exit;
|
|
@@ -1,89 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..9\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
# The header callback will only be called if your libcurl has the
|
|
||||||
# CURLOPT_HEADERFUNCTION supported, otherwise your headers
|
|
||||||
# go to CURLOPT_WRITEFUNCTION instead...
|
|
||||||
#
|
|
||||||
|
|
||||||
my $header_called=0;
|
|
||||||
sub header_callback { print STDERR "header callback called\n"; $header_called=1; return length($_[0])};
|
|
||||||
|
|
||||||
# test for sub reference and head callback
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_HEADERFUNCTION, \&header_callback);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) != 0) {
|
|
||||||
print "not ";
|
|
||||||
};
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
print STDERR "next test will fail on libcurl < 7.7.2\n";
|
|
||||||
print "not " if (!$header_called); # ok if you have a libcurl <7.7.2
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
exit;
|
|
@@ -1,105 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..9\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
# The header callback will only be called if your libcurl has the
|
|
||||||
# CURLOPT_HEADERFUNCTION supported, otherwise your headers
|
|
||||||
# go to CURLOPT_WRITEFUNCTION instead...
|
|
||||||
#
|
|
||||||
|
|
||||||
my $header_called=0;
|
|
||||||
sub header_callback { print STDERR "header callback called\n"; $header_called=1; return length($_[0])};
|
|
||||||
|
|
||||||
# test for sub reference and head callback
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_HEADERFUNCTION, \&header_callback);
|
|
||||||
|
|
||||||
my $body_called=0;
|
|
||||||
sub body_callback {
|
|
||||||
my ($chunk,$handle)=@_;
|
|
||||||
print STDERR "body callback called with ",length($chunk)," bytes\n";
|
|
||||||
print STDERR "data=$chunk\n";
|
|
||||||
$body_called++;
|
|
||||||
return length($chunk); # OK
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# test for ref to sub and body callback
|
|
||||||
my $body_ref=\&body_callback;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, $body_ref);
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) != 0) {
|
|
||||||
print "not ";
|
|
||||||
};
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
|
|
||||||
print STDERR "next test will fail on libcurl < 7.7.2\n";
|
|
||||||
print STDERR "not " if (!$header_called); # ok if you have a libcurl <7.7.2
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
print "not " if (!$body_called);
|
|
||||||
print "ok ".++$count."\n";
|
|
@@ -1,87 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..8\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $body_abort_called=0;
|
|
||||||
sub body_abort_callback {
|
|
||||||
my ($chunk,$sv)=@_;
|
|
||||||
print STDERR "body abort callback called with ",length($chunk)," bytes\n";
|
|
||||||
$body_abort_called++;
|
|
||||||
return -1; # signal a failure
|
|
||||||
}
|
|
||||||
|
|
||||||
# test we can abort a request mid-way
|
|
||||||
my $body_abort_ref=\&body_abort_callback;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, $body_abort_ref);
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) == 0) { # reverse test - this should have failed
|
|
||||||
print "not ";
|
|
||||||
};
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
print "not " if (!$body_abort_called); # should have been called
|
|
||||||
print "ok ".++$count."\n";
|
|
@@ -1,99 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..9\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 0);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
# inline progress function
|
|
||||||
# tests for inline subs and progress callback
|
|
||||||
# - progress callback must return 'true' on each call.
|
|
||||||
|
|
||||||
my $progress_called=0;
|
|
||||||
sub prog_callb
|
|
||||||
{
|
|
||||||
my ($clientp,$dltotal,$dlnow,$ultotal,$ulnow)=@_;
|
|
||||||
print STDERR "\nperl progress_callback has been called!\n";
|
|
||||||
print STDERR "clientp: $clientp, dltotal: $dltotal, dlnow: $dlnow, ultotal: $ultotal, ";
|
|
||||||
print STDERR "ulnow: $ulnow\n";
|
|
||||||
$progress_called++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_PROGRESSFUNCTION, \&prog_callb);
|
|
||||||
|
|
||||||
# Turn progress meter back on - this doesn't work in older libcurls - once its off, its off.
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 0);
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) != 0) {
|
|
||||||
print "not ";
|
|
||||||
};
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
print "not " if (!$progress_called);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
@@ -1,99 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..7\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "http://localhost/cgi-bin/printenv";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL};
|
|
||||||
} else {
|
|
||||||
$url = "";
|
|
||||||
print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
$url = <STDIN>;
|
|
||||||
if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $read_max=1000;
|
|
||||||
|
|
||||||
sub read_callb
|
|
||||||
{
|
|
||||||
my ($maxlen,$sv)=@_;
|
|
||||||
print STDERR "\nperl read_callback has been called!\n";
|
|
||||||
print STDERR "max data size: $maxlen - need $read_max bytes\n";
|
|
||||||
if ($read_max > 0) {
|
|
||||||
my $len=int($read_max/3)+1;
|
|
||||||
my $data = chr(ord('A')+rand(26))x$len;
|
|
||||||
print STDERR "generated max/3=", int($read_max/3)+1, " characters to be uploaded - $data.\n";
|
|
||||||
$read_max=$read_max-length($data);
|
|
||||||
return $data;
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# test post/read callback functions - requires a url which accepts posts, or it fails!
|
|
||||||
#
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl,CURLOPT_READFUNCTION,\&read_callb);
|
|
||||||
Curl::easy::setopt($curl,CURLOPT_INFILESIZE,$read_max );
|
|
||||||
Curl::easy::setopt($curl,CURLOPT_UPLOAD,1 );
|
|
||||||
Curl::easy::setopt($curl,CURLOPT_CUSTOMREQUEST,"POST" );
|
|
||||||
|
|
||||||
if (Curl::easy::perform($curl) != 0) {
|
|
||||||
print "not ";
|
|
||||||
};
|
|
||||||
print "ok ".++$count."\n";
|
|
@@ -1,129 +0,0 @@
|
|||||||
# Test script for Perl extension Curl::easy.
|
|
||||||
# Check out the file README for more info.
|
|
||||||
|
|
||||||
# Before `make install' is performed this script should be runnable with
|
|
||||||
# `make t/thisfile.t'. After `make install' it should work as `perl thisfile.t'
|
|
||||||
|
|
||||||
######################### We start with some black magic to print on failure.
|
|
||||||
|
|
||||||
# Change 1..1 below to 1..last_test_to_print .
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
BEGIN { $| = 1; print "1..10\n"; }
|
|
||||||
END {print "not ok 1\n" unless $::loaded;}
|
|
||||||
use Curl::easy;
|
|
||||||
|
|
||||||
$::loaded = 1;
|
|
||||||
print "ok 1\n";
|
|
||||||
|
|
||||||
######################### End of black magic.
|
|
||||||
|
|
||||||
# Insert your test code below (better if it prints "ok 13"
|
|
||||||
# (correspondingly "not ok 13") depending on the success of chunk 13
|
|
||||||
# of the test code):
|
|
||||||
|
|
||||||
my $count=1;
|
|
||||||
|
|
||||||
# Read URL to get
|
|
||||||
my $defurl = "ftp://user\@localhost//tmp/blah";
|
|
||||||
my $url;
|
|
||||||
if (defined ($ENV{CURL_TEST_URL_FTP})) {
|
|
||||||
$url=$ENV{CURL_TEST_URL_FTP};
|
|
||||||
};# else {
|
|
||||||
#$url = "";
|
|
||||||
#print "Please enter an URL to fetch [$defurl]: ";
|
|
||||||
#$url = <STDIN>;
|
|
||||||
#if ($url =~ /^\s*\n/) {
|
|
||||||
$url = $defurl;
|
|
||||||
#}
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Init the curl session
|
|
||||||
my $curl = Curl::easy::init();
|
|
||||||
if ($curl == 0) {
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
|
|
||||||
|
|
||||||
open HEAD, ">head.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
open BODY, ">body.out";
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
my $errbuf;
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, CURLOPT_URL, $url);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
sub passwd_callb
|
|
||||||
{
|
|
||||||
my ($clientp,$prompt,$buflen)=@_;
|
|
||||||
print STDERR "\nperl passwd_callback has been called!\n";
|
|
||||||
print STDERR "clientp: $clientp, prompt: $prompt, buflen: $buflen\n";
|
|
||||||
print STDERR "\nEnter max $buflen characters for $prompt ";
|
|
||||||
my $data = <STDIN>;
|
|
||||||
chomp($data);
|
|
||||||
return (0,$data);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Now do an ftp upload:
|
|
||||||
|
|
||||||
|
|
||||||
Curl::easy::setopt($curl, Curl::easy::CURLOPT_UPLOAD, 1);
|
|
||||||
|
|
||||||
|
|
||||||
my $read_max=1000;
|
|
||||||
Curl::easy::setopt($curl,CURLOPT_INFILESIZE,$read_max );
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
sub read_callb
|
|
||||||
{
|
|
||||||
my ($maxlen,$sv)=@_;
|
|
||||||
print STDERR "\nperl read_callback has been called!\n";
|
|
||||||
print STDERR "max data size: $maxlen - $read_max bytes needed\n";
|
|
||||||
|
|
||||||
if ($read_max > 0) {
|
|
||||||
my $len=int($read_max/3)+1;
|
|
||||||
my $data = chr(ord('A')+rand(26))x$len;
|
|
||||||
print STDERR "generated max/3=", int($read_max/3)+1, " characters to be uploaded - $data.\n";
|
|
||||||
$read_max=$read_max-length($data);
|
|
||||||
return $data;
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use perl read callback to read data to be uploaded
|
|
||||||
Curl::easy::setopt($curl, Curl::easy::CURLOPT_READFUNCTION, \&read_callb);
|
|
||||||
|
|
||||||
# Use perl passwd callback to read password for login to ftp server
|
|
||||||
Curl::easy::setopt($curl, Curl::easy::CURLOPT_PASSWDFUNCTION, \&passwd_callb);
|
|
||||||
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
my $bytes;
|
|
||||||
|
|
||||||
# Go get it
|
|
||||||
if (Curl::easy::perform($curl) == 0) {
|
|
||||||
Curl::easy::getinfo($curl, Curl::easy::CURLINFO_SIZE_UPLOAD, $bytes);
|
|
||||||
print STDERR "$bytes bytes transferred\n";
|
|
||||||
} else {
|
|
||||||
# We can acces the error message in $errbuf here
|
|
||||||
print STDERR "'$errbuf'\n";
|
|
||||||
print "not ";
|
|
||||||
}
|
|
||||||
print "ok ".++$count."\n";
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
Curl::easy::cleanup($curl);
|
|
||||||
print "ok ".++$count."\n";
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user